Reputation: 201
I am having this problem, I have
private ScheduledExecutorService executor =
Executors.newSingleThreadScheduledExecutor();
and task which is created every 50 millliseconds:
executor.scheduleAtFixedRate(myTask, 0, 50, TimeUnit.MILLISECONDS);
myTask
sometimes take a while to complete (like 2-3 seconds or so), but newSingleThreadScheduledExecutor guarantees that next scheduled myTask will wait until the current one completes.
However, I get this error from time to time:
execute: java.util.concurrent.RejectedExecutionException
What should I do? Thanks
Upvotes: 8
Views: 11477
Reputation: 327
With Java 7 both of them will wait till the first execution is ready and then start the next!
check here:
http://download.java.net/jdk7/archive/b123/docs/api/java/util/concurrent/ScheduledThreadPoolExecutor.html
or here:
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledThreadPoolExecutor.html
Upvotes: -1
Reputation: 403551
Consider what the executor is doing. It is running a single task every 50 milliseconds, as per your instructions. Assuming this task takes less than 50 milliseconds to run, then everything is fine. However, every so often it takes 2-3 seconds to run. When this happens, the executor still tries to execute every 50 milliseconds, but because it only has a single thread, it can't, and rejects those executions that are being triggered while your long-running task is still going. This causes the exception you see.
You have two choices to fix this (assuming you want to stick with a single thread):
Use scheduleWithFixedDelay
rather than scheduleAtFixedRate
. If you read the javadoc carefully, you'll see that scheduleWithFixedDelay
will wait 50 milliseconds between the finishing of one task and the start of the next, so it will never "overlap", even if one of them takes a long time. In contrast, scheduleAtFixedRate
will try to execute every 50 milliseconds, regardless of how long each one takes.
Change the way that the executor handles failures to execute. The default is to log an exception, but you can tell it to ignore it, for example. Take a look at the subclasses of of java.util.concurrent.RejectedExecutionHandler
, for example DiscardPolicy
, which just silently drops the task that can't be run. You can use these by directly constructing ScheduledThreadPoolExecutor
and passing in the handler to the constructor, rather than using the Executors
factory class.
I suspect option (1) is what you want.
Upvotes: 16
Reputation: 9446
This exception will be thrown when either:
I assume the latter is happening. When you execute your task and it takes a long time then subsequent scheduled tasks can not be run because there are not enough threads available in the pool.
Either:
See also ThreadPoolExecutor javadoc
Upvotes: 4