2012-02-20 9 views
5

Ho fatto la seguente errore:Esiste un modo per far funzionare in modo ricorsivo un ExecutorService?

  1. Chiamato Executors.newFixedThreadThreadPool di realizzare la piscina
  2. Impostare un elenco di Callable oggetti, ad esempio che il metodo call a sua volta ha cercato di avviare un'attività sulla stessa piscina filo
  3. metterli nella coda con invokeAll

i risultati sono stati un punto morto sulla coda del executo r servizio.

Il Javadoc che ho letto non sembra proibire questo insieme di attività. Ho dimenticato qualcosa? C'è un modo per personalizzare la coda o il servizio in modo che questo possa funzionare?

+0

ho avuto una domanda simile. Diciamo che il mio pool di thread ha solo un singolo thread in esso. Il mio Callable esterno ottiene il thread e invoca un sub-task Callable. Quindi attende il completamento dell'attività secondaria. Tuttavia, poiché l'unico thread nel pool è già associato all'attività esterna, non verrà mai assegnato all'attività interna, risultando in deadlock. Questa valutazione è corretta o mi manca qualcosa? –

+0

Dopo averci pensato un po 'di più, sembra che si possa entrare in un deadlock se il numero di rami (ovvero il numero di attività che generano attività secondarie) è maggiore del numero di thread nel pool. Pertanto, quando il conteggio dei rami supera il conteggio dei thread, è possibile eseguire le attività secondarie in serie anziché inviarle per l'esecuzione parallela. Non ho provato questo, ma concettualmente sembra che dovrebbe funzionare. –

risposta

3

La mia comprensione della tua domanda è qualcosa come il seguente test-case, che funziona come documentato (come dici tu) e che ho felicemente utilizzato nella produzione. In che modo il tuo esempio differisce da questo?

import java.util.Date; 
import java.util.concurrent.Callable; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.TimeUnit; 

class Scratch { 
    public static void main(String[] args) throws InterruptedException { 
     final ExecutorService pool = Executors.newFixedThreadPool(1); 
     pool.submit(new Callable<Void>() { 
      @Override 
      public Void call() throws Exception { 
       pool.submit(new Callable<Void>() { 
        @Override 
        public Void call() throws Exception { 
         System.out.println(new Date() + ": Second callable being run."); 
         pool.shutdown(); 
         return null; 
        } 
       }); 

       System.out.println(new Date() + ": First callable going to sleep..."); 
       Thread.sleep(2000); 
       System.out.println(new Date() + ": First callable finished!"); 
       return null; 
      } 
     }); 

     pool.awaitTermination(2, TimeUnit.MINUTES); 
    } 
} 

Stampe qualcosa di simile:

Mon Feb 20 01:18:00 GMT 2012: First callable going to sleep... 
Mon Feb 20 01:18:02 GMT 2012: First callable finished! 
Mon Feb 20 01:18:02 GMT 2012: Second callable being run. 
+0

La mia funzione esterna utilizza pool.invokeAll, non pool.submit, quindi è in attesa. E sospetto ora che il problema è che tutti i thread sono usati sui thread 'esterni', quindi nessun lavoro viene fatto all'interno. In altre parole, ero un idiota. – bmargulies

+0

Anche così, un eseguibile Callable dovrebbe essere ancora in grado di 'submit()' un nuovo Callable (come 'submit()' non blocca mai su 'newFixedThreadPool()')? A meno che non stiate usando 'pool.invokeAll()' anche all'interno dei Callables? – FauxFaux

+0

Questo è dentro lucene e non lo so. Ma se tutti i fili sono esauriti all'esterno, l'interno può sottomettersi, ma non progredire mai, e quindi nessuno degli esterni sarà mai completato. – bmargulies

Problemi correlati