我的ThreadPoolExecutor泄漏了内存吗?

时间:2012-10-15 21:28:45

标签: java threadpoolexecutor

我正在使用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运行它(我假设后面的效果更多,堆空间更多)。我很欣赏任何指针,但可能我只是错过了明显的。

1 个答案:

答案 0 :(得分:2)

您可以尝试修改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(我想是这样),你就会避免它。