现在我有一个可调用对象列表,我执行以下操作.
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的方式有效,但我仍然有一些挥之不去的担忧.
>我的方法是使用ExecutorService进行良好的编程实践吗?
>我应该使用ExecutorService的单例实例吗?
>我应该不只是避免并行方法中的I / O操作,还要避免JDBC调用吗?
作为最后一个问题,我试图研究一下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吗?
任何帮助/指导表示赞赏.
解决方法
> OuterCallables是否具有顺序依赖性?如果是这样,你的方法很好,但使用ForkJoinPool会更好,因为它会保持较低的工作线程数.如果没有,最好将一个大的扁平化Callables集合提交给一个Executor.>仅当您想在几个不同的例程中使用ExecutorService并且希望避免传递它时.如果它只在someMethod中使用,那么也可以像你一样在那里实例化它.>您应该避免需要很长时间才能完成的I / O例程.如果您的ExecutorService有4个工作线程且所有这些线程都在I / O上阻塞,那么JVM根本不会使用cpu,即使其他Callables可能正在等待进行cpu密集型工作.只要查询不需要很长时间才能完成,一些JDBC调用就可以了.