重用ThreadPoolExecutor与创建和处置Ad Hoc?

时间:2014-08-13 03:26:52

标签: java multithreading concurrency threadpoolexecutor

我正在构建一个多线程进程,它有几个阶段,每个阶段迭代一个未知数量的对象(来自缓冲查询结果集或文本文件的数十万个)。每个阶段都会为每个对象启动一个runnable或callable,但是所有runnables / callables必须完成才能进入下一个阶段。

我不想使用闩锁或任何类型的同步器,因为我不想损害吞吐量。我怀疑闩锁的内部结构会使同步计数器减慢速度。我也不想在invokeAll()中使用期货列表,因为我想在迭代它时立即开始执行runnables。

但是,为每个阶段创建一个ThreadPoolExecutor,循环并提交所有可运行的东西,然后为每个阶段关闭它似乎是一个功能性的解决方案......

public void runProcess() {

ResultSet rs = someDbConnection.executeQuery(someSQL);

ExecutorService stage1Executor = Executors.newFixedThreadPool(9);
while (rs.next()) { 
//SUBMIT UNKNOWN # OF RUNNABLES FOR STAGE 1
}
rs.close();
stage1Executor.shutdown(); 

rs = someDbConnection.executeQuery(moreSQL);

ExecutorService stage2Executor = Executors.newFixedThreadPool(9);
while (rs.next()) {  
//SUBMIT UNKNOWN # OF RUNNABLES FOR STAGE 2
}
rs.close();
stage2Executor.shutdown();

}

但是,我知道设置线程,线程池以及任何涉及并发的内容构造和销毁都很昂贵。或者也许这不是什么大不了的事情我只是对性能过于谨慎,因为并发性无论如何都会带来昂贵的开销。有更有效的方法吗?使用某种等待完成操作我不知道?

2 个答案:

答案 0 :(得分:3)

如果你销毁线程池并重新启动一个新的线程池,它可能比使用CountDownLatch花费更多!

此外,调用stage1Executor.shutdown();并不保证所有当前线程都会在新的ExecutorService启动并运行之前完成执行。即使致电shutdownNow()也无法保证! (你可能不想调用shutdownNow(),因为你希望线程完成执行。)

唐纳德克努特曾经说过:

  

过早优化是万恶之源。

所以即使你不被我说服 - 最好听他说:)

答案 1 :(得分:1)

设置和拆除少数线程池几乎可以忽略不计。在测试中循环尝试。

使用倒计时锁存器很好,但也许这可能只是复制了ThreadPoolExecutor内部工作并且任务耦合到执行框架。不是这种方法的粉丝。

对于原始代码,ExecutorService采用awaitTermination方法,因此您可以等到工作完成后再进入下一阶段。

我的钱,你的伪代码很好。只需将executor.shutdown()替换为shutdownAndAwaitTermination(ExecutorService),其来源就是:http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html