2013-12-11 15 views
5

Ho un grosso file fino a terabyte, e il mio compito è quello di elaborare riga per riga. Ogni linea dovrebbe prendere 5 secondi per realizzare. Per migliorare le prestazioni di I spedizione il processo per un pool di thread fisso come questoCosa succede se la coda di ExecutorService è piena

ExecutorService executor = Executors.newFixedThreadPool(5);  

while ((line = br.readLine()) != null) { 
    Runnable worker = new WorkerThread(line); 
    executor.execute(worker); 
} 

La mia domanda è che cosa succede se sopraffare coda dell'esecutore mettendo tanti compiti. Getta StackOverflow?

+1

due anni indietro mi è stato chiesto a questa domanda in un'intervista :) – Vipin

+0

@Vipin: e vi ho ottenuto il lavoro? –

+2

Non potevo rispondere a questo. Dopo alcune domande simili ho iniziato a consultare il codice sorgente JDK ovunque possibile. Aiuta a capire meglio il design. – Vipin

risposta

4

Si genera un errore OOM (overhead quater) se non si elabora più velocemente di quanto si mette. Non è possibile ottenere uno StackOverflow in quanto lo stack non cambia molto.

@StinePike chiede una buona domanda. RejectedExecutionException si verifica se non ci sono più thread per elaborare gli elementi fuori dalla coda e la coda è piena. In questo caso l'implementazione predefinita di Executors.newFixedThreadPool(5); utilizzerà un numero illimitato di LinkedBlockingQueue. La nostra unica restrizione è la memoria.

+2

si getta RejectedExecutionException? – stinepike

+2

@StinePike solo se la coda è di dimensioni fisse, che IIRC è una coda illimitata per impostazione predefinita. –

+0

nice .. grazie per la spiegazione +1 – stinepike

3

Come si controlla l'attuazione Executors.newFiexedThreadPool,

public static ExecutorService newFixedThreadPool(int nThreads) { 
    return new ThreadPoolExecutor(nThreads, nThreads, 
            0L, TimeUnit.MILLISECONDS, 
            new LinkedBlockingQueue<Runnable>()); 
} 

compiti saranno gettati in un LinkedBlockingQueue e aspettare per filo da eseguire. Se ci sono troppe attività in attesa, è possibile lanciare OutOfMemory anziché StackOverflow

2

Otterrai OutOfMemoryError perché newFixedThreadPool utilizza una coda di blocco illimitata. È possibile evitarlo creando un'istanza di ThreadPoolExecutor con una coda limitata.

+0

Qual è la differenza tra una coda limitata e una illimitata? –

+1

è circa la capacità della coda. Se v'è un limite alla sua capacità [LinkedBlockingQueue (int capacity)] (http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/LinkedBlockingQueue.html#LinkedBlockingQueue%28int%29) poi la coda è delimitata, mentre [LinkedBlockingQueue()] (http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/LinkedBlockingQueue.html#LinkedBlockingQueue%28%29) è illimitato. – Vasanth

4

Questo potrebbe essere un po 'fuori tema, ma una delle opzioni per questo problema è l'uso di una coda di blocco a lunghezza fissa e l'uso di ThreadPoolExecutor.CallerRunPolicy(). In questo modo, se il consumatore non è abbastanza veloce (quindi la coda si sta riempiendo), il thread del chiamante (produttore) verrà utilizzato per eseguire l'attività stessa. Siamo in grado di inizializzare un esecutore come segue:

executorService = new ThreadPoolExecutor(DEFAULT_THREAD_COUNT, 
     DEFAULT_THREAD_COUNT, 2, TimeUnit.MINUTES, 
     new ArrayBlockingQueue<Runnable>(DEFAULT_QUEUE_LENGTH), 
     new ThreadPoolExecutor.CallerRunsPolicy()); 

From the API: "Un gestore per le attività respinti che esegue l'attività respinto direttamente nel thread chiamante del metodo execute, a meno che l'esecutore è stato arrestato, nel qual caso la compito è scartato. "

Problemi correlati