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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With