繁体   English   中英

我的ThreadPoolExecutor是否正在泄漏内存?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM