2015-11-17 8 views
5

Ich möchte einen Cache-Thread-Pool erstellen, der jedoch als fester Thread fungiert. Zur Zeit habe ich diesen Code:Thread-Pool wird nicht skaliert

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 ""; 
    } 
} 

Wenn ich den Code ausführen ich Ausgabe:

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

Bedeutung nur 2 Fäden machen die ganze Arbeit und keine neuen Worker-Threads werden in den Pool aufgenommen. Sollte der Threadpool nicht mehr Threads erzeugen, wenn Aufgaben in der Warteschlange stehen (in meinem Fall bis zu 10)?

Ich möchte nicht Executors.newCachedThreadPool() verwenden, weil es praktisch keine obere Grenze für maximale Threads hat und es hat corePoolSize 0. Ich möchte immer einige Threads bereit für bessere Reaktionsfähigkeit haben.

----- bearbeiten 1 -----

Danke Aleksey für die Antwort. Wenn ich die Warteschlangenkapazität so anwähle, dass sie sich wie erwartet verhält, habe ich jetzt ein neues Problem.

Die Anzahl der Hintergrundaufgaben ist sehr unterschiedlich. Meistens 0, kann aber für kurze Zeit bis zu 50 gleichzeitige Aufgaben ausführen. Was wäre ein effizienter Weg, damit umzugehen? Beachten Sie, dass die meisten Hintergrundaufgaben nur von kurzer Dauer sind (< 1s), aber auch ein paar langlebige Aufgaben (> 1min).

Wenn ich meinen Threadpool wie folgt aufgebaut:

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

Ich werde höchstwahrscheinlich RejectedExecutionException mit Spitzenauslastung bekommen. Allerdings, wenn ich aufgebaut wie dieser thread:

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

Dann keine neuen Worker-Threads werden jemals da die Warteschlange wird nicht max out hinzugefügt werden.

Die CPU hat mindestens 4 Kerne, das wäre meiner Meinung nach verschwenderisch. Und meistens gibt es überhaupt keine Hintergrundaufgaben (80% der Betriebszeit), also wäre es meiner Meinung nach auch eine Verschwendung eines festen Thread-Pools.

Antwort

4

ThreadPoolExecutor Javadoc sagt:

Wenn eine neue Aufgabe in Verfahren vorgelegt wird execute (Runnable) und weniger als corePoolSize Threads laufen, ein neuer Thread wird erstellt die Anfrage behandeln, auch wenn andere Worker-Threads sind inaktiv. Wenn es mehr als corePoolSize ist aber weniger als maximumPoolSize Fäden ausgeführt wird, wird ein neuer Thread nur dann erstellt werden, wenn die Warteschlange voll

Ihre LinkedBlockingQueue ist nie voll, weil es keine Obergrenze für die Zahl hat von Elementen. Ein Wechsel von new LinkedBlockingQueue() zu new LinkedBlockingQueue(10) würde das lösen.

+0

Vielen Dank für das Aufräumen. Aber jetzt bekomme ich RejectedExecutionException (Poolgröße = 10, aktive Threads = 10, wartende Tasks = 10), da die Warteschlange voll ist und alle aktiven Threads auch aufgebraucht sind. –