我有一堆 Callable
我想并行运行并获取结果。我的机器上有 12 个内核;以下代码在 100% CPU 使用率下按预期工作:
exec = Executors.newFixedThreadPool(maxThreads);
for(Callable<T> job : jobs) exec.submit(job);
// System runs at 100% CPU.
但是,这种情况并不理想,因为我想在任务返回时处理它们的结果。因此,我将 ExecutorService
包装在一个 CompletionService
中,它在 Future
完成时排队:
exec = Executors.newFixedThreadPool(maxThreads);
ecs = new ExecutorCompletionService<T>(exec);
for(Callable<T> job : jobs) ecs.submit(job);
// System runs threads one at a time.
现在我的代码运行速度慢了 12 倍。检查底层代码后,我发现 ExecutorCompletionService
在 ExecutorService
上调用了 execute()
而不是 submit()
,但我不明白这会如何导致它表现出奇怪的行为。
关于可能导致这种情况的原因有什么想法吗?
编辑:这里没有区别。速度变慢是由于在进行此更改的同时对代码的不同部分进行了更改,并且两者之间存在混淆。
最佳答案
execute(...)
应该执行与 submit(...)
相同的操作。唯一的区别是 submit(...)
返回一个 Future
。 ExecutorCompletionService
不需要 future,因为它将提交的任务包装在它自己的内部 Runnable
中。
性能变化必须对其他一些变化进行。我知道您向我们展示了 ECS 构造函数,但只是为了确保您没有将有界 BlockingQueue
传递给 ExecutorCompletionService
对吗?使用有界队列会阻止线程完成并移动到下一个作业,直到作业出队。
我们能看到更多代码吗?
关于java - ExecutorCompletionService 仅在单线程中运行,但 ExecutorService 使用所有 CPU,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14510678/