我有一個 Web 應用程式,其中一個請求可能會呼叫多個必須并行運行的作業。作業涉及通過網路進行通信,因此它們并不完全受 CPU 限制;此類作業的估計持續時間在幾秒到幾分鐘之間。
顯而易見的解決方案是將作業執行委托給專用執行緒池。但是,我想避免一種情況,即一個客戶端(即一個請求)為自己的作業占用了大部分池子,而對其他客戶端一無所獲。同時,創建作業的請求不應阻塞;它應該提交其作業以供執行并立即回傳。從本質上講,我正在尋找的是能夠根據一些自定義標準設定配額的能力,例如,這樣,即使更多的作業已提交到執行緒池,也不會同時運行超過 20 個匹配的作業。可能有什么開箱即用的嗎?
當然,另一種選擇是為每個請求創建一個新的固定執行緒池實體,向其提交作業然后關閉,但感覺這不是正確的做法。
uj5u.com熱心網友回復:
我想不出任何開箱即用的東西。但是,前段時間我已經實施了一個解決類似問題的解決方案,可以進行調整。
舉個例子,假設您想要一個總共有 200 個可用執行緒的執行緒池,但您希望只允許 10 個執行緒作為單個識別符號(在您的情況下:請求 ID)。
您可以做的是創建 20 個單獨的執行緒池,每個執行緒池有 10 個執行緒。然后有一些簡單的邏輯將任務轉發到這些執行緒池之一。它可以完成,即基于hash-of-task-id%number-of-threadpools.
這將保證來自一個請求(或至少具有相同請求 ID)的所有任務都將轉到一個特定的執行程式。
當然這里有一些假設(即你的 id 的哈希值必須分布得很好,這樣當你得到它的模時,它會在執行緒池中均勻地分配 id)和風險(即來自多個請求的任務可能會進入一個池,而其他池可能是空的)。
如果您需要更通用的解決方案,那么恐怕需要更多的實作。
這是上述解決方案的代碼:
public class IdAffiliatiedThreadPool {
private final int executorsCnt;
private final ExecutorService[] executors;
public IdAffiliatiedThreadPool(String name, int executorsCnt, int threadsPerExecutor) {
this.executorsCnt = executorsCnt;
this.executors = new ExecutorService[executorsCnt];
for(int i = 0; i < executorsCnt; i ) {
this.executors[i] = Executors.newFixedThreadPool(threadsPerExecutor);
}
}
public void execute(Object id, Runnable action) {
int threadId = id.hashCode() % executorsCnt;
this.executors[threadId].execute(action);
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/362904.html
