我有一個簡單的web服務在Tomcat容器內運行,這本質上是多線程的。在進入服務的每個請求中,我想對外部服務進行併發呼叫。 java.util.concurrent中的ExecutorCompletionService部分讓我感受到了。我可以爲它提供一個線程池,它將負責執行我的併發調用,並在任何結果準備就緒時通知我。我該如何實現或找到線程安全的CompletionService的等價物?
來處理特定的傳入請求可能看起來像代碼:
void handleRequest(Integer[] input) {
// Submit tasks
CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(Executors.newCachedThreadPool());
for (final Integer i : input) {
completionService.submit(new Callable<Integer>() {
public Integer call() {
return -1 * i;
}
});
}
// Do other stuff...
// Get task results
try {
for (int i = 0; i < input.size; i++) {
Future<Integer> future = completionService.take();
Integer result = future.get();
// Do something with the result...
}
} catch (Exception e) {
// Handle exception
}
}
這應該做工精細和花花公子,但效率非常低,因爲一個新的線程池被分配給每個傳入的請求。如果我將CompletionService作爲共享實例移出,我將遇到多個請求共享相同CompletionService和線程池的線程安全問題。當請求提交任務並獲得結果時,結果不會是他們提交的結果。
因此,我需要的是一個線程安全的CompletionService,它允許我在所有傳入請求中共享一個公共線程池。當每個線程完成一項任務時,應該通知傳入請求的適當線程,以便它可以收集結果。
什麼是最直接的方式來實現這種功能?我相信這種模式已經被應用了很多次,我只是不確定這是Java併發庫提供的東西,還是可以使用某些Java併發構建塊輕鬆構建。
UPDATE:一個警告我忘了提及的是,我希望被任何的我提交的任務完成會立即通知。這是使用CompletionService的主要優勢,因爲它可以分離任務和結果的生產和消耗。我實際上並不關心我得到結果的順序,而且我希望避免不必要的阻塞,等待結果按順序返回。
我是否明白,有一個輸入請求需要啓動input.length()線程,並且需要在所有線程完成後執行一些操作? – 2011-02-16 08:24:11
這是部分正確的。我想要啓動input.length()線程,並且想要在線程完成後立即處理結果,而不管順序如何。我不關心我得到結果的順序,只是在其中任何一個結束時我都會收到通知。 – pmc255 2011-02-16 18:57:29