ThreadPoolExecutor 挂起
Posted
技术标签:
【中文标题】ThreadPoolExecutor 挂起【英文标题】:ThreadPoolExecutor hangs 【发布时间】:2013-12-08 01:38:14 【问题描述】:尝试调试我们应用程序的轮询器线程之一永远不会返回的竞争条件,从而导致未来的轮询器永远不会被调度。抽象地说,在捕获问题的同时隐藏我们的业务逻辑,这就是我们的代码路径。
我们必须更新远程服务器中资源 Y 的某些状态 X。我们有一个资源管理器,它更改资源状态并更新 X 作为更改的副作用。该经理不断地轮询资源,当它认为资源已更新时,它使用ThreadPoolExecutor
来完成工作。这个线程池执行器有一个合理大小的阻塞队列,但最大线程数相当少。线程转储的挂起本身发生在 invokeAll 调用中(除其他外)
我们有理由相信这个池执行器中的核心/最大线程数正忙于做其他事情(如果您愿意,可以更新更多资源状态)。
由于invokeAll返回我们等待的期货,问题是即使执行程序使用的阻塞数据结构足够大以接受通过invokeAll传入的工作但没有足够的可用线程,invokeAll是否会挂起?
【问题讨论】:
【参考方案1】:正如其他用户所指出的,没有一些代码(甚至是伪代码),更清楚地了解“状态X”是什么,以及“资源Y”是什么>" 是,这里的任何人几乎都不可能提供明智的答案。简而言之,您需要一个SSCCE。不过,我会在这里尽力而为;-)。如果您确实发布代码和/或提供更多信息,我会相应地更新我的答案。
来自Java 7 ExecutorService#invokeAll
javadoc:
执行给定的任务,返回一个 Futures 列表,在所有完成后保存它们的状态和结果。 Future.isDone() 对于返回列表的每个元素都是 true。请注意,已完成的任务可能已经正常终止,也可能通过引发异常终止。如果在此操作进行时修改了给定的集合,则此方法的结果是不确定的。
根据您的描述(同样,由于缺乏细节,我无法确定),您的一个工作线程正在挂起。由于您正在调用invokeAll(...)
,因此执行程序正在挂起,因为它正在等待挂起的线程完成。但它永远不会。现在,至于为什么你会得到一个挂起的线程,这是一个完全不同的问题,我们肯定需要查看一些代码。 HTH。
【讨论】:
以上是关于ThreadPoolExecutor 挂起的主要内容,如果未能解决你的问题,请参考以下文章
ThreadPoolExecutor的应用和实现分析(中)—— 任务处理相关源码分析
JAVA 笔记 ThreadPoolExecutor 源码剖析
聊聊高并发(四十)解析java.util.concurrent各个组件(十六) ThreadPoolExecutor源代码分析