Reputation: 1076
I'm using a ThreadPoolExecutor
to run tasks. The backend is a SynchronousQueue
, so if the executor is already perfoming a task, it throws the RejectedExecutionException
. Here's a simple test case:
public class ExecutorTest {
final static Worker worker = new Worker();
public static void main(String[] args) {
ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new SynchronousQueue<Runnable>());
while (true) {
try {
executor.execute(worker);
}catch (RejectedExecutionException e) {
}
}
}
static class Worker implements Runnable {
private int i = 0;
private long start = System.currentTimeMillis();
@Override
public void run() {
try {
Thread.sleep(1000);
System.out.println(++i + " " + (System.currentTimeMillis() - start));
} catch (InterruptedException ex) {
}
}
}
}
The expected bahavious is: Execute the worker and after sleeping for a second, print out i (representing how often the worker has been executed so far) and the amount of milliseconds since the worker was created. So I'm expecting:
1 1015
2 2015
3 3016
4 4017
This works fine for a while, but after almost on hour:
2919 2922196
2920 2942951
2921 2990407
So the amount of time between one worker execution and the next one is 20 seconds (2919->2920) and 38 seconds (2920->2921) and so forth. Everything becomes extremely slow and the jvm spends a lot of time in garbage collection. Finally (after a few days) I run into an OutOfMemoryError.
I'm running this with -Xmx8M (I assume the effect appears much later with more heap space) on Oracle's JVM 1.7.0_07 on a 64bit Linux machine. I'd appreciate any pointers, but probably I'm just missing the obvious.
Upvotes: 8
Views: 4761
Reputation: 21
You can try to modify the ThreadPoolExecutor
instantiation. You just have to add an argument to the constructor to use a RejectExecutionHandler
that will silently discard rejected tasks.
public static void main(String[] args) {
ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new SynchronousQueue<Runnable>(), new ThreadPoolExecutor.DiscardPolicy());
while (true) {
executor.execute(worker);
}
}
So if your problem comes from repeated RejectedExecutionException
(and I think so), you will avoid it.
Upvotes: 2