java - Callable 与 Runnable 中使用 "ExecutorCompletionService"的问题

标签 java concurrency executorservice

我一直在使用 ExecutorCompletionService 中的示例代码,并将以下示例代码放在一起。 solve() 中的代码按预期工作并打印
1<br/> 2<br/> 3<br/> 4<br/> 5<br/> solve2() 中的代码不会打印任何内容,而且实际上永远不会退出。 ecs 是在将作业提交到 ExecutionService 之前还是之后构建并不重要。

是否无法将 CompletionService 构造与 FutureTasks 一起使用?我已经重写了我的生产代码以直接 get() FutureTask 的结果,而不是尝试从 ExecutorCompletionService 中 get() 它们,但它(当前)导致了一些看起来困惑的东西。简而言之,下面的solve2有什么问题?谢谢。

import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;

public class sample {
public static class stringCallable implements Callable<String>{
    String mstring;

    stringCallable(String s) {mstring = s;}
    @Override
    public String call() throws Exception {
        // TODO Auto-generated method stub
        return mstring;
    }
};

public static void main(String[] args) {
    // TODO Auto-generated method stub
    ArrayList<Callable<String>> list = new ArrayList<Callable<String>>();
    ExecutorService es = Executors.newFixedThreadPool(1);
    Executor e = Executors.newSingleThreadExecutor();
    list.add(new stringCallable("1"));
    list.add(new stringCallable("2"));
    list.add(new stringCallable("3"));
    list.add(new stringCallable("4"));
    list.add(new stringCallable("5"));

    try {
        solve(e, list);
    } catch (InterruptedException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    } catch (ExecutionException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
    System.out.println ("Starting Solver 2");

    try {
        solve2(es, list);
    } catch (InterruptedException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    } catch (ExecutionException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
}

static void solve(Executor e, Collection<Callable<String>> solvers)throws InterruptedException, ExecutionException {
    CompletionService<String> ecs = new ExecutorCompletionService<String>(e);
    for (Callable<String> s : solvers)
     ecs.submit(s);
    int n = solvers.size();
    for (int i = 0; i < n; ++i) {
        String r = ecs.take().get();
        if (r != null)
            use(r);
    }
}

static void solve2(ExecutorService e, Collection<Callable<String>> solvers)throws InterruptedException, ExecutionException {
    for (Callable<String> s : solvers){
        FutureTask<String> f = new FutureTask<String>(s);
          e.submit(f);
    }
    CompletionService<String> ecs = new ExecutorCompletionService<String>(e);
    int n = solvers.size();
    for (int i = 0; i < n; ++i) {
        String r = ecs.take().get();
        if (r != null)
            use(r);
    }
}

private static void use(String r) {
    System.out.println (r);
}

}

最佳答案

solve2 ,当您创建ExecutorCompletionService时使用现有的ExecutorService ,它提交的任务会被包装器忽略,因为它使用单独的 LinkedBlockingQueue 。提交的任务不会被继承。因此,当您执行 ecs.take().get(); 时,您的代码会阻塞。因为ExecutorCompletionService本身没有任何已提交的任务。

此外,您不需要专门创建 FutureTask 来提交到 ExecutorCompletionService 。这些 future 任务已在内部为您创建。这就是为什么你会得到 Future<String>调用ecs.take();时.

鉴于此,您的solve2功能完全没用。您已经在 solve1 中正确执行了此操作。 .

关于java - Callable 与 Runnable 中使用 "ExecutorCompletionService"的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1888449/

相关文章:

java - 为什么 Java Collections 的移除方法不是通用的?

java - 从字符串中调用颜色类型

apache-spark - PySpark - 运行进程

java - 如何从可调用接口(interface)返回 future 对象(executorService.submit 的内部工作)

java.util.concurrent.Future.get() 不返回

java - 使用JSP代码动态更改DIV标签内容

java - 使用 twitter4j 使用多线程从 twitter 获取数据

c++ - 哪些策略可以有效地处理异构多核架构上的并发读取?

java - SplittableRandom 有什么意义?

java - 多线程 Java 仅使用一个线程