Advanced Java Services | Executors.newScheduledThreadPool(int) |
Der zurückgegebene ScheduledExecutorService ist ein vollwertiger ScheduledThreadPoolExecutor wie der Quellcode zeigt.
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { return new ScheduledThreadPoolExecutor(corePoolSize); }
Damit ist die Queue wie zuvor eine BlockingQueue<Runnable> und wird realisiert durch die statische innere Klasse ScheduledThreadPoolExecutor$DelayedWorkQueue
/** * Specialized delay queue. To mesh with TPE declarations, this * class must be declared as a BlockingQueue<Runnable> even though * it can only hold RunnableScheduledFutures. */ static class DelayedWorkQueue extends AbstractQueue<Runnable> implements BlockingQueue<Runnable> {
Ebenso ist die ThreadFactory wie bei allen Executoren die packageprivate statische innere Klasse DefaultThreadFactory der Factoryklasse Executors.
Für single shots reicht ein ExecutorService mit einem ThreadPool der Größe eins, siehe also die vorigen Beispiele.
Die Arbeitsweise dieses Algorithmus ist natürlich dieselbe wie im vorigen Beispiel, man kann höchstens fragen, ob bei einem größeren Pool verschiedene Threads arbeiten.
Um das zu klären, variieren wir das entprechend vorige Beispiel und definieren einen ThreadPool der Größe drei
private static void periodicShot_FixedDelay_ScheduledThreadPool() { ScheduledExecutorService stse = Executors.newScheduledThreadPool(3); ... stse.scheduleWithFixedDelay(ru, 2, 3, TimeUnit.SECONDS); ... }
Das Ergebnis kann folgendermaßen aussehen
Executors-ScheduledExecutorService ScheduledThreadPool starts at 2016-03-21T14:12:36.999 pool-1-thread-1 start: 2016-03-21T13:12:39.009Z pool-1-thread-1 duration: 2 pool-1-thread-1 end: 2016-03-21T13:12:41.024Z pool-1-thread-1 start: 2016-03-21T13:12:44.025Z pool-1-thread-1 duration: 2 pool-1-thread-1 end: 2016-03-21T13:12:46.025Z pool-1-thread-2 start: 2016-03-21T13:12:49.026Z pool-1-thread-2 duration: 2 pool-1-thread-2 end: 2016-03-21T13:12:51.026Z pool-1-thread-2 start: 2016-03-21T13:12:54.028Z pool-1-thread-2 duration: 4 pool-1-thread-2 end: 2016-03-21T13:12:58.028Z pool-1-thread-2 start: 2016-03-21T13:13:01.029Z pool-1-thread-2 duration: 4 pool-1-thread-2 end: 2016-03-21T13:13:05.029Z shutdown end main
Zwar gibt es zwei Threads, aber sie können nur nacheinander laufen.
Hier interessiert nur die Frage, ob es sich überlappende Threads gibt um Verzögerungen zu vermeiden.
Wiederum ändern wir in unserem Beispiel nur eine Zeile
private static void periodicShot_FixedDelay_ScheduledThreadPool() { ScheduledExecutorService stse = Executors.newScheduledThreadPool(3); ... stse.scheduleWithFixedDelay(ru, 2, 3, TimeUnit.SECONDS); ... }
Ein möglicher Ablauf
Executors-ScheduledExecutorService ScheduledThreadPool starts at 2016-03-21T14:42:19.349 pool-1-thread-1 start: 2016-03-21T13:42:21.359Z // 21 +0 pool-1-thread-1 duration: 2 pool-1-thread-1 end: 2016-03-21T13:42:23.374Z pool-1-thread-1 start: 2016-03-21T13:42:24.359Z // 24 +0 pool-1-thread-1 duration: 2 pool-1-thread-1 end: 2016-03-21T13:42:26.359Z pool-1-thread-2 start: 2016-03-21T13:42:27.359Z // 27 +0 pool-1-thread-2 duration: 4 pool-1-thread-2 end: 2016-03-21T13:42:31.359Z pool-1-thread-2 start: 2016-03-21T13:42:31.359Z // 30 +1 pool-1-thread-2 duration: 4 pool-1-thread-2 end: 2016-03-21T13:42:35.359Z pool-1-thread-2 start: 2016-03-21T13:42:35.359Z // 33 +2 pool-1-thread-2 duration: 2 pool-1-thread-2 end: 2016-03-21T13:42:37.360Z pool-1-thread-2 start: 2016-03-21T13:42:37.360Z // 36 +1 pool-1-thread-2 duration: 2 pool-1-thread-2 end: 2016-03-21T13:42:39.360Z pool-1-thread-2 start: 2016-03-21T13:42:39.360Z // 39 +0 pool-1-thread-2 duration: 4 pool-1-thread-2 end: 2016-03-21T13:42:43.360Z pool-1-thread-2 start: 2016-03-21T13:42:43.360Z // 42 +1 pool-1-thread-2 duration: 4 pool-1-thread-2 end: 2016-03-21T13:42:47.360Z pool-1-thread-2 start: 2016-03-21T13:42:47.360Z // 45 +2 pool-1-thread-2 duration: 2 shutdown end main pool-1-thread-2 end: 2016-03-21T13:42:49.360Z
Es laufen zwei Threads, aber wie bei einem SingleThreadPool laufen die Threads nicht überlappend und es wird versucht die vorlorene Zeit aufzuholen.