Advanced Java Services | Executors.newCachedThreadPool() |
Der CachedThreadPool bestimmt selbst mit wie vielen Threads er eine Liste von Runnables oder Callables abarbeitet. Er erzeugt bei Bedarf neue Threads oder verwendet auch alte wieder. Threads, die 60 Sekunden lang nicht verwendet wurden, werden aus dem Pool entfernt. Auf diese Weise werden Resourcen gespart und so die Performance verbessert. Der CachedThreadPool ist gut geeignet für viele kurzlebige Prozesse, hier hat er eine bessere Performance als andere ThreadPools.
Das Beispiel arbeitet mit denselben Callables wie beim letzten Beispiel zu FixedThreadPool. Dem CachedThreadPool werden 5 Tasks über submit() übergeben.
Die Tasks erledigen ihre Aufgabe in fünf Schritten.
class CTask implements Callable<String> { private int i; public CTask(int i) { this.i = i; } public String call() throws Exception { String name = Thread.currentThread().getName(); for(int j = 0; j < 5; j++) { // Perform some work... System.out.format("%s, c%d, completed: %3d%% %s\n", Thread.currentThread().getName(), i, 20*j, LocalTime.now()); TimeUnit.MILLISECONDS.sleep((int) (Math.random() * 1000)); } System.out.format("%s, c%d, completed: 100%% %s\n\n", Thread.currentThread().getName(), i, LocalTime.now()); return name; } }
Und werden mit submit() übergeben.
private static void startCallablesWithSubmit() { ExecutorService ftp = Executors.newCachedThreadPool(); // Arrays anlegen CTask[] ctask = new CTask[5]; for(int i=0 ; i < 5; i++) { ctask[i] = new CTask(i); } for(int i=0 ; i < 5; i++) { ftp.submit(ctask[i]); } ftp.shutdown(); }
Eine mögliche Ausgabe. Man sieht, daß 5 Threads im Pool arbeiten und daß die Abarbeitung keineswegs mit dem Task beginnen muß der als erstes an submit() übergeben wird.
end main pool-1-thread-4, c3, completed: 0% 16:02:01.270 pool-1-thread-1, c0, completed: 0% 16:02:01.270 pool-1-thread-2, c1, completed: 0% 16:02:01.271 pool-1-thread-3, c2, completed: 0% 16:02:01.270 pool-1-thread-5, c4, completed: 0% 16:02:01.270 pool-1-thread-1, c0, completed: 20% 16:02:01.425 pool-1-thread-2, c1, completed: 20% 16:02:01.525 pool-1-thread-2, c1, completed: 40% 16:02:01.673 pool-1-thread-1, c0, completed: 40% 16:02:01.745 pool-1-thread-4, c3, completed: 20% 16:02:01.780 pool-1-thread-3, c2, completed: 20% 16:02:01.879 pool-1-thread-5, c4, completed: 20% 16:02:01.941 pool-1-thread-5, c4, completed: 40% 16:02:02.087 pool-1-thread-2, c1, completed: 60% 16:02:02.175 pool-1-thread-3, c2, completed: 40% 16:02:02.252 pool-1-thread-1, c0, completed: 60% 16:02:02.347 pool-1-thread-2, c1, completed: 80% 16:02:02.401 pool-1-thread-5, c4, completed: 60% 16:02:02.620 pool-1-thread-4, c3, completed: 40% 16:02:02.649 pool-1-thread-5, c4, completed: 80% 16:02:02.720 pool-1-thread-4, c3, completed: 60% 16:02:02.763 pool-1-thread-4, c3, completed: 80% 16:02:02.918 pool-1-thread-5, c4, completed: 100% 16:02:02.978 pool-1-thread-1, c0, completed: 80% 16:02:03.027 pool-1-thread-4, c3, completed: 100% 16:02:03.035 pool-1-thread-3, c2, completed: 60% 16:02:03.079 pool-1-thread-3, c2, completed: 80% 16:02:03.246 pool-1-thread-2, c1, completed: 100% 16:02:03.308 pool-1-thread-1, c0, completed: 100% 16:02:03.540 pool-1-thread-3, c2, completed: 100% 16:02:03.935
Ein Blick in den Quellcode zeigt, daß die Methode ein Objekt des Typs ThreadPoolExecutor liefert das mit einer SynchronousQueue arbeitet.
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());
}
Executors.newCachedThreadPool() liefert einen vorkonfigurierten ThreadPoolExecutor, dessen ThreadPool quasi beliebig groß werden kann. Nicht verwendeten Threads warten eine Minute auf neue Aufgaben, dann werden Sie aus dem Pool entfernt. Im Gegensatz zu den vorhergehenden ExecutorServices arbeitet er mit einer SynchronousQueue<Runnable>.