Reputation: 142
I have an app that allows users to batch add watermarks to images. The app would only use one thread and can only add one watermark at a time.
I want the user to be able to change the number of watermark tasks[threads] running at a time: maybe [1-5] in settings, and I can't use a fixedThreadPool, as it has a fixed pool size.
I looked into using a ThreadPoolExecutor private static ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newCachedThreadPool();
and each time the user changes the number of threads I invoke the ThreadPoolExecutor.setMaxPoolSize(newMaxThreadCount).
Now when I try to submit say 15 image watermark tasks to the executor with a maximum pool size of 3, I get the following exception:
java.util.concurrent.RejectedExecutionException: Task com.darkmental.zeondownloader.app.main.phototools.watermark.BulkWatermarkTask$$Lambda$710/1861585081@1e2d8ad4 rejected from java.util.concurrent.ThreadPoolExecutor@24d02747[Running, pool size = 3, active threads = 3, queued tasks = 0, completed tasks = 0]
I expected the ThreadPoolExecutor to have the same behavior as a fixedThreadPool where I can have a pool size of 10 and still submit as many tasks as I want, but I didn't. How can I do that?
Upvotes: 1
Views: 1537
Reputation: 3510
A look at the JavaDoc shows, that this behaviour is intended.
New tasks submitted in method execute(java.lang.Runnable) will be rejected when the Executor has been shut down, and also when the Executor uses finite bounds for both maximum threads and work queue capacity, and is saturated.
So in your case, your queue seems to be full or doesn't accept any new items.
I haven't seen how you actually created your ThreadPoolExecutor
, but I would guess, that you need to specify a sufficent BlockingQueue
in the constructor.
EDIT: This probably happens, because Executors.newCachedThreadPool()
is unbounded and creates a new Thread every time, if there is no cached Thread available. However setting the maximum pool size interferes with this and the task is rejected via the RejectedExecutionHandler
.
I currently can't reproduce the scenario, but you probably can change the active AbortPolicy
to ThreadPoolExecutor.CallerRunsPolicy
via setRejectedExecutionHandler(ThreadPoolExecutor.CallerRunsPolicy)
. This result in the calling Thread to execute the new tasks instead of throwing an Exception.
Upvotes: 3