2012-03-28 11 views
6

Considerate seguente codice:Esecuzione di un ExecutorService all'interno di SwingWorker è una buona pratica?

 SwingWorker<Void, Void> sworker = new SwingWorker<Void, Void>() { 

     @Override 
     protected Void doInBackground() throws Exception { 
      ExecutorService executor = Executors.newFixedThreadPool(5); 
      try { 
       for (int j = 0; j < 5; j++) { 
        Callable<Object> worker = new MyCallableImpl(); 
        Future<Object> future = executor.submit(worker); 
        array[j] = future.get(); 
       } 
      } catch (InterruptedException e) { 
       // some code here 
      } catch (ExecutionException e) { 
       // some code here 
      } 
       // some code here 
      executor.shutdown(); 
      return null; 
     } 

    }; 
    sworker.execute(); 

Come ho detto nel titolo: si tratta di una buona pratica per invocare ExecutorService all'interno doInBackground() metodo di SwingWorker? Funziona per me (JDK1.7), la GUI non è bloccata e più thread dal pool Executor sono in esecuzione in background, ma ho ancora qualche dubbio ...

risposta

2

Il codice di cui sopra non ha molto senso per me.

Se l'obiettivo è garantire che la GUI resti reattiva mentre è in esecuzione un'attività di lunga durata, non è necessario utilizzare lo ExecutorService poiché il meccanismo fornisce già tale meccanismo.

+0

Sì, lo so, ma voglio eseguire più thread (Callables) all'interno di SwingWorker. Come posso farlo senza involucro non necessario Executor all'interno di SwingWorker? – DoktorNo

+0

Mi piacerebbe sbarazzarmi del tutto di "SwingWorker" allora. Se una qualsiasi di queste attività modifica i componenti Swing, avvolgere la chiamata usando 'SwingUtilities.invokeLater' – mre

+0

Sì, stanno modificando i componenti Swing (il codice non viene mostrato, per evitare confusione). Proverò la tua soluzione nel frattempo. – DoktorNo

2

Per ulteriore risposta di mre. Non ha senso perché la tua esecuzione è in realtà a thread singolo. Il doInBackground si invierà all'esecutore e attenderà il completamento di quella singola attività, quindi invierà un altro.

È necessario inviare allo stesso modo, ma memorizzare gli Future s restituiti in un elenco di un certo tipo, quindi ottenere ciascuno di essi dopo che tutte le attività sono state inviate.

Non mi interessa il doInBackground inviare questi lavori in modo asincrono come fa mre. Se stai provando a inviare un numero di attività e hai solo N inviato in un dato momento, non dovresti assolutamente farlo tramite SwingWorker.doInBackground. Usando un ExectorService + SwingUtilities.invokeLater penso sia il modo migliore.

E per chiarire qualsiasi confusione, lo invokeLater deve essere utilizzato solo qui quando l'attività all'interno di ExecutorService è completa e tutto ciò che deve fare è aggiornare il componente dell'interfaccia utente.

Edit: Esempio per affrontare il tuo commento

protected Void doInBackground() throws Exception { 
    ExecutorService executor = Executors.newFixedThreadPool(5); 
    List<Future> futures = ...; 
    try { 
     for (int j = 0; j < 5; j++) { 
      Callable<Object> worker = new MyCallableImpl(); 
      futures.add(executor.submit(new Callable<Object>(){ 
       public Object call(){ 
        //expensive time consuming operation 
        final String result = ...;//result from consuming operation 
        SwingUtilities.invokeLater(new Runnable(){ 
         public void run(){ 
          jLabel.setText(result); 
         } 
        }); 
        return new Object(); 
       } 
      )); 
     } 
     for(Future<Object> f :futures)f.get(); 
     executor.shutdown(); 
    return null; 
} 

Notate come il invokeLater è fatto per fare un semplice aggiornamento? Questo non dovrebbe causare il blocco dell'EDT.

+0

Ci proverò.A proposito, qual è la differenza tra SwingUtilities.invokeLater() e EventQueue.invokeLater()? – DoktorNo

+0

Nella distribuzione standard di Java, nulla. 'SwingUtilities.invokeLater' si limita a delegare a' EventQueue.invokeLater'. Basta accoppiare tutte le funzionalità necessarie in SwingUtilities. –

+0

Ho bloccato tutte le chiamate per la modifica della GUI in invokeLater, all'interno di un runonym anonymour e la GUI è ancora bloccata. Cosa ho sbagliato? BTW: l'intero codice wrom my snippet viene eseguito nel metodo invocato dal listener di eventi (dopo aver premuto un pulsante). – DoktorNo

2
  • può eseguire SwingWorkers esempio dalla esecutore

  • devono accettare che esecutore non si preoccupa SwingWorkers ciclo di vita e viceversa

  • necessario implementare PropertyChangeListener per SwingWorker

  • exmple here

Problemi correlati