Executors
provides newCachedThreadPool()
and newScheduledThreadPool()
, but not newCachedScheduledThreadPool()
, what gives here? I have an application that receives bursty messages and needs to schedule a fairly lengthy processing step after a fixed delay for each. The time constraints aren't super tight, but I would prefer to have more threads created on the fly if I exceed the pool size and then have them trimmed back during periods of inactivity. Is there something I've missed in the concurrent library, or do I need to write my own?

- 398,947
- 96
- 818
- 769

- 12,395
- 10
- 46
- 49
4 Answers
By design the ScheduledThreadPoolExecutor is a fixed size. You can use a single threaded version that submits to a normal ExecutorService for performing the task. This event thread + worker pool is fairly ease to coordinate and the flexibility makes up for the dedicated thread. I've used this in the past to replace TimerTasks and other non-critical tasks to utilize a common executor as a system-wide pool.

- 9,178
- 3
- 35
- 39
Suggested here Why does ScheduledThreadPoolExecutor only accept a fixed number of threads? workaround:
scheduledExecutor = new ScheduledThreadPoolExecutor(128); //no more than 128 threads
scheduledExecutor.setKeepAliveTime(10, TimeUnit.SECONDS);
scheduledExecutor.allowCoreThreadTimeOut(true);

- 1
- 1

- 16,647
- 10
- 125
- 197
-
5**Caution using this workaround**: consider this from the [documentation of ScheduledThreadPoolExecutor](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ScheduledThreadPoolExecutor.html): _"Additionally, it is almost never a good idea to set corePoolSize to zero or use **allowCoreThreadTimeOut** because this may leave the pool without threads to handle tasks once they become eligible to run."_ – rmoestl Mar 03 '15 at 08:18
-
3After poking around with this, I could not get the `ScheduledThreadPoolExecutor` to exhibit this behaviour. With the default implementation, if the thread pool is empty, `ensurePrestart()`, a private method called by all schedule methods, will create a worker to handle the new task. A github gist: https://gist.github.com/Groostav/600edf739a39cbbb33cbd64ad385d621 – Groostav Jul 01 '17 at 22:39
-
1read: this implies that the comment @rmoestl is referencing is erroneous, and that GKislin's strategy is sound. It is still of course very concerning that the docs suggest this isn't a valid strategy, and its entirely possible that I'm missing something. – Groostav Jul 01 '17 at 22:42
java.util.concurrent.Executors
is nothing more than a collection of static convenience methods that construct common arrangements of executors.
If you want something specific that isn't offered by Executors
, then feel free to construct your own instance of the implemention classes, using the examples in Executors
as a guide.

- 398,947
- 96
- 818
- 769
-
4Imho this answer is misleading for the stated problem as it suggests that one can simply construct an Executor that meets this particular requirements. But reading the documentation of [ScheduledThreadPoolExecutor](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ScheduledThreadPoolExecutor.html) indicates that calling several tuning methods inherited from [ThreadPoolExecutor](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ThreadPoolExecutor.html) "have no useful effect" and thus the desired behaviour seems to be unsupported by `ScheduledThreadPoolExecutor`. – rmoestl Mar 03 '15 at 08:14
Like skaffman says, Executors
is only a collection of factory method. if you need a particular instance, you can always check all existing Executor
implementors. In your case, i think that calling one of the various constructors of ScheduledThreadPoolExecutor would be a good idea.

- 22,052
- 14
- 85
- 185