2012-04-14 48 views
6

在我的项目中,我构建了一个Java执行框架,它接收来自客户端的工作请求。工作(不同规模)被分解为一组任务,然后排队等待处理。有单独的队列来处理每种类型的任务,每个队列都与一个ThreadPool相关联。 ThreadPools的配置方式使得引擎的整体性能最佳。工作/任务窃取ThreadPoolExecutor

这种设计可以帮助我们有效地平衡请求,而大型请求不会占用系统资源。然而,有时当某些队列为空并且它们各自的线程池闲置时,解决方案变得无效。

为了让这个更好,我正在考虑实现一个工作/任务窃取技术,以便重载队列可以从其他ThreadPools获得帮助。但是,这可能需要实现我自己的执行程序,因为Java不允许将多个队列与ThreadPool关联,并且不支持工作窃取概念。

阅读Fork/Join,但这看起来不适合我的需求。任何建议或替代方法来构建此解决方案可能会非常有帮助。

感谢 安迪

+1

您应该考虑如何保持所有CPU忙碌。如果您正在充分利用您的CPU,那么您的某些线程是否空闲并不重要。 – 2012-04-14 12:45:50

+0

如果您的线程池拥有与cpus一样多的线程,则即使所有其他线程池都处于空闲状态,任何单独的线程池都可以“窃取”所有cpus。 – 2012-04-14 12:50:53

+0

@PeterLawrey - 这是真的,但如果有很多池,那么如果所有池中的所有线程同时工作,则性能可能会很差。 – jtahlborn 2012-04-14 12:55:33

回答

1

,你可以实现自定义的BlockingQueue实现(我想你主要需要实现offer()take()方法),这是由“主”队列和0或多个辅助队列支持。如果非空,take将始终从主要支持队列中取出,否则它会从辅助队列中拉出。

事实上,最好有一个池,其中所有员工都可以访问所有队列,但是“更喜欢”一个特定的队列。您可以通过为不同的工作人员分配不同的优先级来获得最佳的工作比率。在满负荷的系统中,您的工作人员应该以最佳比例工作。在一个负载不足的系统中,你的工作人员应该能够帮助其他队列。

+0

这似乎是一个好主意,我倾向于尝试使用POC。 – 2012-04-14 13:19:54

2

你考虑过ForkJoinPool吗? fork-join框架以一种很好的模块化方式实现,因此您可以使用工作线程池。

+1

阅读API但仍无法弄清楚它与常规ThreadPoolExecutor的不同之处。也许错过了一些更好的方面。 – 2012-04-14 13:21:41

+0

是的,我明白了,您所拥有的实际上是您现在想要灵活分配的分区方案 - 让分区边界根据工作负载而变化。 “偷工减料”可能是一个更专门的术语,涉及罚款任务粒度 - 在一个线程上执行的任务会产生子任务并将其推送到其自己的deque,以便其他线程可以窃取其工作。所以也许如果你用术语“线程池分区”进行研究,你会发现一些适合你的情况。 – 2012-04-14 13:31:53

2

Java 8在Executors类中具有工厂和实用方法。 有一个工作窃取线程池(here)的实现,我相信这正是你想要的。

+0

我看到的唯一缺点是,它会根据需要创建新的ForkJoinThreads,而不是从全局池中借用这些线程 - 可能是客户端可以通过的公共池或池。 – 2017-11-20 22:50:55