Java: SingleThreadScheduledExecutor & java.util.concurrent.RejectedExecutionException

I have this problem, I have

private ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); 

and a task that is created every 50 milliseconds:

 executor.scheduleAtFixedRate(myTask, 0, 50, TimeUnit.MILLISECONDS); 

myTask sometimes takes some time (for example, 2-3 seconds or so), but newSingleThreadScheduledExecutor ensures that the next scheduled myTask will wait for the current to complete.

However, I get this error from time to time:

execute: java.util.concurrent.RejectedExecutionException

What should I do? Thanks

+7
java multithreading concurrency exception executor
source share
3 answers

See what the performer does. It performs one task every 50 milliseconds, according to your instructions. Assuming less than 50 milliseconds is required to complete this task, everything will be fine. However, every time it often takes 2-3 seconds. When this happens, the executor still tries to execute every 50 milliseconds, but since it has only one thread, it cannot and rejects those launches that start while your long-term task is still ongoing. This raises the exception you see.

You have two options to fix this (if you want to stick to one thread):

  • Use scheduleWithFixedDelay , not scheduleAtFixedRate . If you read javadoc carefully, you will see that scheduleWithFixedDelay will wait 50 milliseconds between the completion of one task and the start of the next, so it will never β€œoverlap”, even if one of them takes a lot of time. In contrast, scheduleAtFixedRate will try to execute every 50 milliseconds, regardless of how long each takes.

  • Change the way the handler executes the failures. By default it is used to register an exception, but you can say that it ignores it, for example. Take a look at subclasses of java.util.concurrent.RejectedExecutionHandler , such as DiscardPolicy , which simply disables a task that cannot be started. You can use them by directly building the ScheduledThreadPoolExecutor and passing them to the constructor, rather than using the Executors factory class.

I suspect option (1) is what you want.

+11
source share

This exception will be thrown if:

  • You will complete the work of the Contractor
  • Executor limits for work queue or maximum threads exceeded.

I guess the latter is happening. When you complete your task and take a long time, subsequent scheduled tasks cannot be started because there are not enough threads in the pool.

Or:

  • Use a larger pool size or use cachedThreadPool
  • Change the rejection policy, for example, use ThreadPoolExecutor.CallerRunsPolicy
  • Create a separate Contractor to launch tasks with a large circulation and run them from the scheduled task. In fact, you can do this using the same Executor instance, which will increase the pool size.

See also ThreadPoolExecutor javadoc

+4
source share
-one
source share

All Articles