通过ExecutorCompletionService执行任务是否并行化?

时间:2009-06-26 15:24:39

标签: java multithreading concurrency

我向ExecutorCompletionService提交了5个作业,但似乎就像作业按顺序执行一样。传递给ExecutorCompletionService构造函数的ExecutorService是使用newCacheThreadPool表单创建的。我做错了吗?

更新每项工作基本上都是进行数据库查询&一些计算。 ExecutorCompletionService的代码从javadoc中解除。我刚用自己的自定义Callable实现替换了Callables。

4 个答案:

答案 0 :(得分:4)

ExecutorCompletionService nothing 与作业执行方式有关,这只是检索结果的便捷方式。

默认情况下,

Executors.newCachedThreadPool在单独的线程中执行任务,可以并行,具体如下:

  • 任务是独立的,并且不是例如同步内部的同一个对象;
  • 您有多个硬件CPU线程。

最后一点值得解释。虽然没有任何保证,但实际上Sun JVM支持当前正在执行的线程,因此它永远不会被替换为另一个线程。这意味着你的5个任务最终可能会因为JVM的实现而串行执行,而不是例如一台多核机器。

答案 1 :(得分:1)

我认为你的意思是Executors.newCachedThreadPool()。如果是这样,执行应该按照您的预期进行并行化。

答案 2 :(得分:1)

  

每项工作基本上都是进行数据库查询&一些计算。 ExecutorCompletionService的代码从javadoc中解除。我刚用自己的自定义Callable实现替换了Callables。

在这种情况下,你是否确定你没有错误地认为他们已经执行,因为你按顺序检索结果?
在你的callables中输入一些调试日志记录行来排除这种情况,和/或看看这个有限的使用场景:

public static void main(String... args) throws InterruptedException, ExecutionException {
    List<Callable<String>> list = new ArrayList<Callable<String>>();
    list.add(new PowersOfX(2));
    list.add(new PowersOfX(3));
    list.add(new PowersOfX(5));
    solve(Executors.newCachedThreadPool(), list);
}

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)
            System.out.println("Retrieved: " + r);
    }
}

static class PowersOfX implements Callable<String> {
    int x;
    public PowersOfX(int x) {this.x = x;}
    @Override
    public String call() throws Exception {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 10; i++) {
            sb.append(Math.pow(2, i)).append('\t');
            System.out.println(Math.pow(x, i));
            Thread.sleep(2000);
        }
        return sb.toString();
    }
}

执行此操作,您将看到数字是混合生成的(因此同时执行),但仅检索结果不会显示此级别详细信息..

答案 3 :(得分:0)

执行将取决于许多事情。例如:

  • 完成工作所需的时间
  • 线程池中的线程数(缓存的线程池只有在认为需要时才会创建线程)

按顺序执行不一定是错误的。