线程池死锁:设计或检测
Threadpool Deadlock: designing against or detecting
我希望这不会过于宽泛;我的问题是 "How do I design a service with multiple Threadpools which can't deadlock itself?".
我拥有一项 Web 服务,可根据单个用户请求扇出 100 个线程,以低延迟执行数据聚合。有许多 ExecutorServices 包装固定线程池散落在我的服务中,我需要帮助解决一个有趣的方法,这可能会造成死锁。
我有一个线程池 A
用于保存发出网络请求的线程,还有另一个线程池 B
用于保存它们的 "owning" 线程;业务逻辑的聚合位可能会分散到少数请求中。此外,当可以通过聚合 3 个更简单的子聚合来完成聚合时,B
中的线程偶尔会向线程池 B
提交一些工作。
这个模式就是问题所在。让我们考虑一种提交给 B
的请求 x
的样式,它导致将额外的请求 x'
提交给 B
。我们还考虑 B
是一个包含 50 个线程的固定线程池。当50个x
类型的请求同时进来时,B
中的所有线程都用来处理这些请求。他们都将 x1
提交给 B
,后者在队列中等待线程。然后所有请求的所有处理都处于死锁状态 60 秒,直到超时并且 x
请求所有 return 异常。
我拥有的东西 considered/tried:
- 调整数字。可以连接的最大用户数为 50,
B
中的线程数为 100。防止出现问题,但似乎是一个 hack,当另一个开发人员在一年内调整不相关的数字并且没有人能弄清楚为什么我们锁定一次时就会崩溃负载下一周。我想在设计中解决这个问题。
B
将展开的工作提交给 B'
,一个新的线程池。不起作用,因为此扇出可能会进行多个步骤(我是否创建 B''
、B'''
、...?)
B
没有最大线程数。可能可以接受,但似乎很危险。
- 另一个模型(更回调?)线程不提交并等待相同的工作单元;相反,他们提交工作并将 "callback" 提交到
"run-after" 池。这样,没有什么可以等待自己池中的东西。有先例吗,这是个好主意吗?
- 一起折叠所有线程池并删除最大值?
您的 "more callbackish" 答案似乎大部分都可以通过 CompletionStage API in Java 8 - the lack of a "runAfterAllAsync" method means you may have to do some external work to get something to happen after your group of 3 subtasks, but this is where I'd start to look. This tutorial 为您解决,有一个示例可能会有一些帮助。
我希望这不会过于宽泛;我的问题是 "How do I design a service with multiple Threadpools which can't deadlock itself?".
我拥有一项 Web 服务,可根据单个用户请求扇出 100 个线程,以低延迟执行数据聚合。有许多 ExecutorServices 包装固定线程池散落在我的服务中,我需要帮助解决一个有趣的方法,这可能会造成死锁。
我有一个线程池 A
用于保存发出网络请求的线程,还有另一个线程池 B
用于保存它们的 "owning" 线程;业务逻辑的聚合位可能会分散到少数请求中。此外,当可以通过聚合 3 个更简单的子聚合来完成聚合时,B
中的线程偶尔会向线程池 B
提交一些工作。
这个模式就是问题所在。让我们考虑一种提交给 B
的请求 x
的样式,它导致将额外的请求 x'
提交给 B
。我们还考虑 B
是一个包含 50 个线程的固定线程池。当50个x
类型的请求同时进来时,B
中的所有线程都用来处理这些请求。他们都将 x1
提交给 B
,后者在队列中等待线程。然后所有请求的所有处理都处于死锁状态 60 秒,直到超时并且 x
请求所有 return 异常。
我拥有的东西 considered/tried:
- 调整数字。可以连接的最大用户数为 50,
B
中的线程数为 100。防止出现问题,但似乎是一个 hack,当另一个开发人员在一年内调整不相关的数字并且没有人能弄清楚为什么我们锁定一次时就会崩溃负载下一周。我想在设计中解决这个问题。 B
将展开的工作提交给B'
,一个新的线程池。不起作用,因为此扇出可能会进行多个步骤(我是否创建B''
、B'''
、...?)B
没有最大线程数。可能可以接受,但似乎很危险。- 另一个模型(更回调?)线程不提交并等待相同的工作单元;相反,他们提交工作并将 "callback" 提交到 "run-after" 池。这样,没有什么可以等待自己池中的东西。有先例吗,这是个好主意吗?
- 一起折叠所有线程池并删除最大值?
您的 "more callbackish" 答案似乎大部分都可以通过 CompletionStage API in Java 8 - the lack of a "runAfterAllAsync" method means you may have to do some external work to get something to happen after your group of 3 subtasks, but this is where I'd start to look. This tutorial 为您解决,有一个示例可能会有一些帮助。