简体   繁体   English

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

[英]Is my ThreadPoolExecutor leaking memory?

I'm using a ThreadPoolExecutor to run tasks. 我正在使用ThreadPoolExecutor运行任务。 The backend is a SynchronousQueue , so if the executor is already perfoming a task, it throws the RejectedExecutionException . 后端是一个SynchronousQueue ,因此,如果执行程序已经执行了任务,则会抛出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. 预期的行为是:执行该工作程序,并在睡眠一秒钟后,打印出i(表示到目前为止该工作程序被执行的频率)以及自创建该工作程序以来的毫秒数。 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. 因此,一个工作人员执行与下一个工作执行之间的时间是20秒(2919-> 2920)和38秒(2920-> 2921),依此类推。 Everything becomes extremely slow and the jvm spends a lot of time in garbage collection. 一切都变得非常缓慢,并且jvm花费大量时间进行垃圾回收。 Finally (after a few days) I run into an OutOfMemoryError. 终于(几天后),我遇到了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. 我在64位Linux机器上的Oracle JVM 1.7.0_07上使用-Xmx8M(我认为效果会在很晚之后出现更多的堆空间)运行。 I'd appreciate any pointers, but probably I'm just missing the obvious. 我会感激任何指针,但是可能我只是想念那些显而易见的东西。

You can try to modify the ThreadPoolExecutor instantiation. 您可以尝试修改ThreadPoolExecutor实例化。 You just have to add an argument to the constructor to use a RejectExecutionHandler that will silently discard rejected tasks. 您只需要向构造函数添加一个参数即可使用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);                
  }
}

So if your problem comes from repeated RejectedExecutionException (and I think so), you will avoid it. 因此, 如果您的问题来自重复的RejectedExecutionException (我认为是这样),则可以避免这种情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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