2015-11-17 32 views
5

Desidero creare un pool di thread memorizzato nella cache, ma funziona come uno fisso. Attualmente ho questo codice:Pool di ridimensionamenti non ridimensionato

public class BackgroundProcesses { 

    public static void main(String[] args) throws InterruptedException, ExecutionException { 
     //ExecutorService threadPool2 = Executors.newCachedThreadPool(); 
     ExecutorService threadPool = new ThreadPoolExecutor(2, 10, 180, TimeUnit.SECONDS, new LinkedBlockingQueue<>()); 
     for (int i = 0; i < 800; i++) { 
      Callable<String> task = new Task(); 
      threadPool.submit(task); 
     } 
    } 
} 

class Task implements Callable<String> { 

    @Override 
    public String call() throws Exception { 
     Thread.sleep(100); 
     System.out.println(Thread.currentThread().getName() + " is ready"); 
     return ""; 
    } 
} 

Se corro il codice ottengo uscita:

pool-1-thread-1 is ready 
pool-1-thread-2 is ready 
pool-1-thread-1 is ready 
pool-1-thread-2 is ready 
... 

Significato solo 2 le discussioni stanno facendo tutto il lavoro e non nuovi thread di lavoro vengono aggiunti al pool. Non dovrebbe il threadpool generare più thread se le attività sono in attesa in coda (fino a 10 nel mio caso)?

Non voglio usare Executors.newCachedThreadPool() perché non ha praticamente alcun limite superiore sui thread massimi e ha corePoolSize 0. Voglio avere sempre dei thread pronti per una migliore reattività.

----- ----- modificare 1

Grazie Aleksey per la risposta. L'impostazione della capacità di accodamento sta comportando il comportamento previsto, ma ora ho un nuovo problema.

La quantità di attività in background varia molto. La maggior parte delle volte 0 ma può andare fino a 50 attività simultanee per brevi periodi. Quale sarebbe un modo efficace per gestire questo? Tenere presente che la maggior parte delle attività in background è di breve durata (< 1s) ma anche alcune attività di lunga durata (> 1min).

Se ho impostato la mia threadpool in questo modo:

ExecutorService threadPool = new ThreadPoolExecutor(2, 10, 180, TimeUnit.SECONDS, new LinkedBlockingQueue<>(10)); 

sarò più probabile ottenere RejectedExecutionException con picchi di utilizzo. Tuttavia, se ho impostato ThreadPool in questo modo:

ExecutorService threadPool = new ThreadPoolExecutor(2, 10, 180, TimeUnit.SECONDS, new LinkedBlockingQueue<>(200)); 

Poi sarà mai aggiunti nuovi thread di lavoro perché la coda non sarà max fuori.

La CPU ha almeno 4 core, quindi questo sarebbe uno spreco a mio parere. E la maggior parte delle volte non ci sono attività di background (80% del tempo di attività), quindi mantenere un pool di thread fisso sarebbe anche dispendioso secondo me.

risposta

4

ThreadPoolExecutor Javadoc dice:

Quando una nuova attività è presentata nel metodo execute (Runnable), e meno di discussioni corePoolSize sono in esecuzione, un nuovo thread è stato creato per gestire la richiesta, anche se altri i thread di lavoro sono inattivi. Se ci sono più di corePoolSize ma meno di maximumPoolSize discussioni in esecuzione, verrà creato un nuovo thread solo se la coda è piena

tuo LinkedBlockingQueue è mai pieno, perché non ha un limite superiore al numero di elementi. Cambiando new LinkedBlockingQueue() a new LinkedBlockingQueue(10) risolverebbe quello.

+0

Grazie per averlo chiarito. Ma ora sto ricevendo RejectedExecutionException (dimensione del pool = 10, thread attivi = 10, attività in coda = 10) poiché la coda viene riempita e vengono utilizzati anche tutti i thread attivi. –