這是更多的Java併發設計問題。我正在研究需要爲許多不同客戶端處理許多消息的應用程序。如果兩條消息具有不同的客戶端名稱,則可以並行處理它們。但是,如果它們具有相同的客戶端名稱,則需要按順序進行處理。使用Java線程池,如何根據消息特性並行處理一些消息和其他消息?
實現此目的的最佳方式是什麼?
我目前的實現非常簡單:我寫了一個名爲OrderedExecutorPool的包裝類。它有一個單線程執行程序的列表。在其提交的方法,它下面的找出將任務提交到執行:
int executorNum = Math.abs(clientName.hashCode()) % numExecutors;
executorList.get(executorNum).submit(task);
這保證了與同一客戶的所有消息去同一個執行者,同時還支持並行方式爲不同的客戶端處理的消息。
有幾個與此設計問題:
1)如果大多數客戶的名字有相同的散列碼,那麼只有少數執行者正在做的工作
2)如果一個客戶有很多消息,只有一個執行者可能無法跟上
有沒有一個優雅的解決方案可以解決上述缺點的問題?
編輯 clientName只是一個字符串。我只是調用它的String.hashCode()方法。
你是否用合理的方法重載hashCode? 它確保您始終會爲唯一字符串返回唯一值嗎? 你確定你總是少於2^32個唯一的客戶端名稱(因此是hashcode)嗎? 你確定你現在的hashCode實現是否是無碰撞的? 如果你對任何這些問題回答「否」......你犯了一個錯誤,你的應用程序會崩潰/在某些時候產生錯誤的結果。 – specializt 2014-09-12 16:46:25
「如果一個客戶端有很多消息,只有一個執行者可能無法跟上」,因爲您需要單個客戶端進行串行處理,唯一的選擇是少做一些工作,或者使其效率更高。 – 2014-09-12 16:48:46
注意:Math.abs(Integer.MIN_VALUE)<0.您可以使用'&'代替。例如'(clientName.hashCode()&Integer.MIN_VALUE)%numExecutors;'或如果numExecutors是2的冪'clientName&(numExecutors - 1);' – 2014-09-12 16:51:20