2009-07-24 9 views
6

Sto appena iniziando a esaminare Futures e ScheduledExecutorService in Java, e mi chiedo perché il mio Callable non sia in esecuzione sul programma che ho indicato. In questo codice di esempio, il callable viene eseguito una volta, ma l'app non viene mai completata, né l'attività viene eseguita di nuovo, che è ciò che mi aspettavo che accadesse (sono sicuro che il problema è con le mie aspettative).Ricerca di Clarity su Java ScheduledExecutorService e FutureTask

I cavi funzionano correttamente; Le callebles sembrano bloccarsi per sempre, ma non sono sicuro del perché .... Cosa mi sto perdendo?

Grazie!

public class ExecutorExample { 

    /** 
    * @param args 
    * @throws ExecutionException 
    * @throws InterruptedException 
    */ 
    public static void main(String[] args) throws InterruptedException, ExecutionException { 

     ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(5); 

     FutureTask<ArrayList<String>> ft1 = new FutureTask<ArrayList<String>>(new Callable<ArrayList<String>>(){ 
      @Override 
      public ArrayList<String> call() { 
       ArrayList<String> stuff = new ArrayList<String>(); 
       for(int i = 0;i<10;i++){ 
        String thing ="Adding " + i + " to result"; 
        stuff.add(thing); 
        System.out.println(thing); 

       } 
       return stuff; 
      }}); 

     scheduler.scheduleAtFixedRate(ft1, 0, 1, TimeUnit.SECONDS); 

     System.out.println(ft1.get()); 
     System.out.println(ft1.isDone()); 

    } 
} 

risposta

8

Il problema è che FutureTask viene utilizzato, e come la sua documentazione di classe dice: "Una volta che il calcolo è stato completato, il calcolo non può essere riavviato o annullati."

Dopo che il metodo FutureTask è stato invocato una volta, le chiamate successive vengono restituite immediatamente, senza delegare all'istanza Callable dell'attività.

Solo un Runnable può essere utilizzato come attività ricorrente e ciò non consente di restituire un risultato. Invece, assegnare all'attività una richiamata che può richiamare alla fine del suo metodo run, per riportare i risultati di ciascuna esecuzione dell'attività ai listener in altri thread.

+1

Non sono sicuro di seguirlo. FutureTask implementa Runnable e mi aspetterei che invochi il metodo call() e memorizzi il risultato. Quindi mi aspetto che get() blocchi fino a quando il lavoro è terminato, o restituisco immediatamente il risultato memorizzato nella cache. Quindi lo scheduler non dovrebbe eseguire il FutureTask, risultando in call() e il risultato memorizzato nella cache per la successiva raccolta? –

+1

Sì, ma solo una volta. Eventuali invocazioni programmate dopo il primo chiamerebbero 'run' sul FutureTask, ma quel metodo di esecuzione" cortocircuiti "senza richiamare' call' su Callable. Ma lo scheduler non ne è a conoscenza e continua a funzionare per richiamare il FutureTask, quindi il programma non termina. – erickson

+0

Ha perfettamente senso. Ero così a testa bassa nelle javadoc per gli Executor e il suo genere e ho completamente perso quella linea ovvia in FutureTask. Come domanda successiva, se quello che voglio accadere come risultato del mio compito è che un BlockingQueue viene aggiornato, è preferibile passare semplicemente quella coda in ogni eseguibile, o implementare un listener che vivrebbe al di fuori del eseguibile che poi manipola la coda in base ai risultati? Grazie ancora –

Problemi correlati