[英]Is my ThreadPoolExecutor leaking memory?
我正在使用ThreadPoolExecutor
运行任务。 后端是一个SynchronousQueue
,因此,如果执行程序已经执行了任务,则会抛出RejectedExecutionException
。 这是一个简单的测试用例:
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) {
}
}
}
}
预期的行为是:执行该工作程序,并在睡眠一秒钟后,打印出i(表示到目前为止该工作程序被执行的频率)以及自创建该工作程序以来的毫秒数。 所以我期望:
1 1015
2 2015
3 3016
4 4017
可以正常工作一会儿,但是将近一个小时后:
2919 2922196
2920 2942951
2921 2990407
因此,一个工作人员执行与下一个工作执行之间的时间是20秒(2919-> 2920)和38秒(2920-> 2921),依此类推。 一切都变得非常缓慢,并且jvm花费大量时间进行垃圾回收。 终于(几天后),我遇到了OutOfMemoryError。
我在64位Linux机器上的Oracle JVM 1.7.0_07上使用-Xmx8M(我认为效果会在很晚之后出现更多的堆空间)运行。 我会感激任何指针,但是可能我只是想念那些显而易见的东西。
您可以尝试修改ThreadPoolExecutor
实例化。 您只需要向构造函数添加一个参数即可使用RejectExecutionHandler
,它会以静默方式丢弃被拒绝的任务。
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);
}
}
因此, 如果您的问题来自重复的RejectedExecutionException
(我认为是这样),则可以避免这种情况。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.