如何实现或找到一个线程安全的CompletionService的等价物? [英] How can I implement or find the equivalent of a thread-safe CompletionService?
问题描述
我有一个简单的Web服务在Tomcat容器中运行,本质上是多线程的。在每个进入服务的请求中,我想对外部服务进行并发调用。 java.util.concurrent中的ExecutorCompletionService部分存在。我可以提供一个线程池,它将负责执行我的并发调用,当任何结果准备就绪时,我会收到通知。
I have a simple web service running inside a Tomcat container, which by nature is multi-threaded. In each request that comes into the service, I want to make concurrent calls to an external service. The ExecutorCompletionService in java.util.concurrent gets me partly there. I can provide it a thread pool, and it will take care of executing my concurrent calls and I will be notified when any of the results are ready.
特定的传入请求可能如下所示:
The code to process a particular incoming request might look like:
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
}
}
这应该工作正常和dandy,但是效率很低,因为一个新的线程池被分配给每个传入的请求。如果我将CompletionService作为共享实例移出,我将遇到多个请求共享相同CompletionService和线程池的线程安全问题。
This should work fine and dandy, but is quite inefficient since a new thread pool is being allocated for each incoming request. If I move the CompletionService out as a shared instance, I will run into thread-safety problems with multiple requests sharing the same CompletionService and thread pool. As requests submit tasks and get results, the results they get not be the ones they submitted.
因此,我需要的是一个线程安全的完成服务,它允许我共享跨所有传入请求的公共线程池。当每个线程完成一个任务时,应该通知传入请求的相应线程,以便它可以收集结果。
Thus, what I need is a thread-safe CompletionService that allows me to share a common thread pool across all incoming requests. As each thread completes a task, the appropriate thread for the incoming request should be notified so that it can gather the results.
实现这种类型的最直接的方法是什么功能?我确信这种模式已经应用了很多次;我只是不确定这是否是由Java并发库提供的,或者如果可以使用一些Java并发构建块轻松构建。
What's the most straightforward way to implement this sort of functionality? I'm sure this pattern has been applied many times; I'm just not sure if this is something provided by the Java concurrency library, or if can be easily built using some of the Java concurrency building blocks.
UPDATE:一个警告,我忘了提及是,我想在任何我提交的任务完成后立即收到通知。这是使用CompletionService的主要优点,因为它可以分离任务和结果的生产和消耗。我实际上并不关心我得到结果的顺序,我想避免不必要的阻塞,同时等待结果按顺序返回。
UPDATE: one caveat I forgot to mention is that I would like to be notified as soon as any of my submitted tasks complete. That's the primary advantage of using a CompletionService, as it decouples the production and consumption of the tasks and results. I don't actually care about the order in which I get the results back, and I'd like to avoid unnecessarily blocking while waiting for the results to be returned in order.
推荐答案
您共享执行程序
,但不包括 CompletionService
。
我们有 AsyncCompleter 这样做,并处理所有的簿记,允许您:
We have an AsyncCompleter that does exactly this and handles all the bookkeeping, allowing you to:
Iterable<Callable<A>> jobs = jobs();
Iterable<A> results async.invokeAll(jobs);
结果
直到结果可用
这篇关于如何实现或找到一个线程安全的CompletionService的等价物?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!