2013-04-10 65 views
0

我们正在使用通过ExecutorService#newCachedThreadPool创建的CachedThreadPool。 (Java 1.6)。我们在代码中的其他地方发现错误:“无法创建新的本地线程”,我们诊断为内存不足问题。当这个问题发生时,我们调用提交的代码块(我们使用提交,不执行)会变慢。我们怀疑ThreadPool在尝试创建新线程来处理任务时遇到了“无法创建新的本地线程”的相同问题,但我们无法确定。从(ExecutorService)捕获异常CachedThreadPool

有没有办法赶上从ExecutorService的内部异常? 为了100%清楚,我不是在谈论给予ExecutorService的任务,而是从ExecutorService本身。

+0

也许你应该做一个线程转储和看到所有的线程会。这不应该发生。 – 2013-04-10 23:25:31

+0

这绝对是一个系统负载问题。我得到它不应该去。这是由于下游的依赖性失败以及我们在我们这边尝试了逻辑。线程全部排队等待重试。 – 2013-04-11 21:14:19

回答

2

Executors.newCachedThreadPool创建一个具有无限的最大线程池大小(注意ThreadPoolExecutor构造函数的第二个参数)一ThreadPoolExecutor

public static ExecutorService newCachedThreadPool() { 
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 
            60L, TimeUnit.SECONDS, 
            new SynchronousQueue<Runnable>()); 
} 

这意味着,如果你在提交任务比消耗速度较快,新主题将是为每个新任务创建,最终达到系统限制并引发“无法创建新的本地线程”异常。

要解决这个问题,您需要更改的ThreadPoolExecutor配置:

  1. 使用合理的ThreadPoolExecutor。
  2. 选择一个适当的拒绝策略时,ThreadPoolExecutor耗尽。

例如:

ExecutorService executorService = new ThreadPoolExecutor(5,200, 
          60L, TimeUnit.SECONDS, 
          new ArrayBlockingQueue(1000), 
          Executors.defaultThreadFactory(), 
          new ThreadPoolExecutor.CallerRunsPolicy()); 

请阅读JavaDocs详细的配置信息。

+0

谢谢。我一直在挖掘文档,并得到它为什么会发生,但我想知道是否有任何方法来捕捉错误?我是否必须编写自己的ThreadFactory? – 2013-04-11 21:15:10

+0

@JohnHinnegan我不明白你为什么想要发现错误。我认为使用长时间运行任务的无限制池大小的线程池是错误的设计。 – ericson 2013-04-12 02:21:02

+0

他们没有长时间运行。我并不认为一个无限的游泳池是有风险的或者显然是错误的。但是,如果主机上的其他内容正在启动,则固定池可能会出现此问题。我试图在我的系统中构建健壮的监控,并且这个错误在我们的系统的一部分中突然出现并且未被发现。我知道这是错误,因为我们在其他地方发现了它(显然它对JVM来说是全局的)。当你回答的时候,我并没有注意到RejectedExecutionHandler是什么。我认为这回答了我的问题。我想我可以实现其中的一个来处理异常。 – 2013-04-12 13:43:55

0

你可以使用实现Runnable接口的自定义类excpetions的集合内,像这样:

public class MyRunnable implements Runnable { 
    private List<Exception> exceptions; 

    ... 

    public void addException(Exception e) { ... } 
    public void getExceptions(){ ... } 
} 

所有可运行后完成自己的执行,你可以检查它们内部异常,并抛出另一个异常响应。