我有一堆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
调用了execute()
而不是ExecutorService
上的submit()
,但是我看不到这将如何导致它表现出怪异的行为。关于什么可能导致此的任何想法?
编辑:这里没有区别。变慢是由于在进行此更改的同时对代码的不同部分进行了更改,并且两者之间存在混淆。
最佳答案
execute(...)
应该与submit(...)
具有相同的功能。唯一的区别是submit(...)
返回Future
。 ExecutorCompletionService
不需要将来,因为它将提交的任务包装在其自己的内部Runnable
中。
性能更改必须与其他更改一起执行。我知道您向我们展示了ECS构造函数,但只是为了确保您没有将有限的BlockingQueue
传递给ExecutorCompletionService
,对吗?使用有界队列将使线程无法完成并转移到下一个作业,直到作业出队。
我们可以看到更多代码吗?
关于java - ExecutorCompletionService仅在单个线程中运行,但是ExecutorService使用所有CPU,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14510678/