2012-04-14 71 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