我开始学习ExecutorService类。文档(和在线教程)说总是调用ExecutorService.shutDown()来回收资源。但是,文档还说在调用shutDown()之后,不会接受任何新任务。所以,我的问题是,每当我需要并行化数据处理时,我是否始终必须实例化一个新的ExecutorService?
现在我有一个可调用对象列表,我会执行以下操作。
public void someMethod() {
List<OuterCallable> outerCallables = getOuterCallables();
ExecutorService executor = Executor.newFixedThreadPool(NUM_CPUS);
executor.invokeAll(tasks);
executor.shutDown();
}
但是,我的OuterCallable还使用InnerCallable并行分割数据或执行数据处理。
public class OuterCallable implements Callable<Long> {
public Long call() throws Exception {
long result = 0L;
List<InnerCallable> innerCallables = getInnerCallables();
ExecutorServices executor = Executor.newFixedThreadPool(NUM_CPUS);
executor.invokeAll(tasks);
executor.shutDown();
return result;
}
}
我不记得它是用于ExecutorService还是Fork / Join方法,但我记得文档和教程说操作数据的实际并行过程不应该涉及I / O操作,一切都应该在内存中完成。但是,在我的InnerCallable中,我实际上正在进行JDBC调用(此处未显示)。
最终,我使用ExecutorService的方式有效,但我仍有疑虑。
作为最后一个问题,我试图研究一下Fork / Join vs ExecutorService。我遇到了一篇完全抨击Fork / Join API /类的文章。学习Fork / Join值得吗?我在stackoverflow和其他地方看到了一些文章,其中测试用于比较Fork / Join和ExecutorService,并且有图表显示了Fork / Join vs ExecutorService的更好的CPU使用率(通过Windows任务管理器)。但是,当我使用ExecutorService(JDK 1.7.x)时,我的CPU使用率是最大值。使用最新的JDK改进了ExecutorService吗?
感谢任何帮助/指导。
答案 0 :(得分:4)
您应该添加awaitTermination
次来电,因为shutDown
会在不等待Callables完成的情况下返回。除此之外,
OuterCallable
是否有顺序依赖?如果是这样,你的方法很好,但使用ForkJoinPool会更好,因为它会保持较低的工作线程数。如果没有,最好将Callable
s的大扁平集合提交到单个Executor
。someMethod
中使用,那么也可以像你一样在那里实例化它。