2015-02-04 112 views
3

我希望這不是過於寬泛;我的問題是「如何設計一個不能自鎖死鎖的多線程池服務?」。線程池死鎖:針對或檢測

我擁有一個Web服務,它可以在單個用戶請求中扇出100個線程,以低延遲執行數據聚合。有很多ExecutorServices在我的服務中包裹着固定線程池,我需要幫助解決這個可能造成死鎖的有趣方式。

我有一個線程池A它用於保持線程發出網絡請求,另一個線程池B用於保存其「擁有」線程;商業邏輯的聚合位可能會引發少量請求。此外,當B中的線程偶爾將工作位提交給線程池B時,可以通過聚合3個更簡單的子聚合來完成聚合。

這種模式是問題所在。讓我們考慮提交給B的請求類型x,這導致請求x'的另外請求被提交給B。我們也考慮B是50個線程的固定線程池。當x類型的50個請求同時進入時,B中的所有線程都用於處理這些請求。他們都將x1提交到B,它們位於等待線程的隊列中。然後,所有請求的所有處理都處於死鎖狀態60秒,直到超時命中並且x請求所有返回異常。

事情我已經考慮/嘗試:

  • 調整數。可以連接的最大用戶數是50,B中的線程數是100.防止出現問題,但是當另一個開發人員在一年內調整不相關數字時似乎會破壞黑客,而且沒有人能夠弄清楚爲什麼我們每週在負載下鎖定一次。我想在設計中解決這個問題。
  • B提交扇出工作到B',一個新的線程池。不起作用,因爲此扇出可能會執行多個步驟(我是否創建了B'',B''',...?)
  • B沒有最大線程數。可能可以接受,看起來很危險。
  • 另一種模式(更多callbackish?)線程不提交併等待同一工作單元;而是他們提交工作並向 「運行後」池中提交「回調」。這樣,任何東西都無法在自己的游泳池中等待。有沒有先例,這是一個好主意嗎?
  • 將所有線程池合併在一起並刪除最大值?
+0

我認爲這是一個很好的問題。你應該嘗試更多的事件導向(或者你提到的回調)。你可以嘗試threadpools,event-queues,[actors](http://akka.io/),甚至可以用非常棒的[lmax ringbuffer disruptor](https://github.com/LMAX-Exchange/disruptor)短期任務。我建議你使用基礎庫來完成這個任務,比如[RxJava](https://github.com/ReactiveX/RxJava)或者[Reactor](http:// spring。IO /博客/ 2013/05/13 /反應器-A-基礎換異步應用 - 上的-JVM /)。只是避免線程,你的要求指向別的地方。 –

回答

2

你「更callbackish」的答案似乎是它會被大多通過CompletionStage API在Java中8你解決 - 缺乏「runAfterAllAsync」的方法意味着你可能需要做一些外部的工作得到的東西發生在你的三個子任務組之後,但這是我開始看的地方。 This tutorial有一個例子,可能有一些幫助。