8

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

5
  • Please be more specific about what yyou mean by "from time to time". That exception should only be thrown at the moment of calling execute() on the ExecutorService. Commented Dec 21, 2009 at 3:11
  • Actually, RejectedExecutionException is throwable by executor.scheduleAtFixedRate() Commented Dec 21, 2009 at 3:23
  • @Andrey, you need to give us significantly more information, starting with a stack trace showing the exception. Commented Dec 21, 2009 at 3:24
  • @Jim, yes, I mean to say "at the moment the job is submitted", as opposed to "from time to time" :) Commented Dec 21, 2009 at 3:29
  • Yes, sometimes RejectedExecutionException is thrown when I call scheduleAtFixedRate (not Always, but I guess that it starts to throw the exception when my myTask takes more time to complete than always). Commented Dec 21, 2009 at 5:06

3 Answers 3

16

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):

  1. 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.

  2. 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.

Sign up to request clarification or add additional context in comments.

1 Comment

@skaffman: actually it is exactly the opposite of what you said in 1. :) javadoc: scheduleAtFixedRate: If any execution of this task takes longer than its period, then subsequent executions may start late, but will not concurrently execute
4

This exception will be thrown when either:

  1. You have shutdown the Executor
  2. The Executor's bounds for its work queue or maximum threads have been exceeded.

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:

  1. Use use a larger pool size or use cachedThreadPool
  2. Change the rejection policy to for example use ThreadPoolExecutor.CallerRunsPolicy
  3. Create a separate Executor for running the long run tasks and run these from your scheduled task. In actual fact you can do this using the same Executor instance providing that you increase the pool size.

See also ThreadPoolExecutor javadoc

1 Comment

How to use cachedThreadPool in my situation? executor.scheduleAtFixedRate(myTask, 0, 50, TimeUnit.MILLISECONDS); How is it possible to change ThreadPoolExecutor rejection policy? Thank you
-1

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.