如何实现或找到一个线程安全的CompletionService的等价物? [英] How can I implement or find the equivalent of a thread-safe CompletionService?

查看:149
本文介绍了如何实现或找到一个线程安全的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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆