我向ExecutorCompletionService提交了5个作业,但似乎就像作业按顺序执行一样。传递给ExecutorCompletionService构造函数的ExecutorService是使用newCacheThreadPool表单创建的。我做错了吗?
更新每项工作基本上都是进行数据库查询&一些计算。 ExecutorCompletionService的代码从javadoc中解除。我刚用自己的自定义Callable实现替换了Callables。
答案 0 :(得分:4)
ExecutorCompletionService
nothing 与作业执行方式有关,这只是检索结果的便捷方式。
Executors.newCachedThreadPool
在单独的线程中执行任务,可以并行,具体如下:
最后一点值得解释。虽然没有任何保证,但实际上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)
执行将取决于许多事情。例如:
按顺序执行不一定是错误的。