我是java并发的新手,想问下面的基本问题。我正在创建一个ThreadPoolExecutor来提高性能,如下所示:
int n = Runtime.getRuntime().availableProcessors()
ExecutorService executor = Executors.newFixedThreadPool(n);
for( int i = 0; i < n; i++)
executor.execute(new Work());
线程池中的所有线程完成任务后,我需要正确关闭池。我试过这个:
while(true){
if(executor.isTerminated()){
executor.shutdownNow();
break;
}
}
但是我不确定,因为我认为我们浪费了大量的处理器资源来确定执行者的终止。
什么是正确的解决方案?
UPD:可运行的任务:
public class Work implements Runnable{
private String sql;
public Work() {
//init sql
}
@Override
public void run() {
JdbcTemplate template = new JdbcTemplate(dataSource);
@SuppressWarnings("unchecked")
List<Integer> ints = template.queryForList(sql, Integer.class);
//Storing the list into a global cache
}
}
答案 0 :(得分:2)
在关闭ExecutorService
时,似乎有一些神秘的东西。
来自the documentation of shutdown()
:
启动有序关闭,其中执行先前提交的任务,但不接受任何新任务。
所以你要做的就是在提交所有任务后调用shutdown()
,确切的时间无关紧要。它们不必在那时完成。 ThreadPoolExecutor
将完成所有任务,然后清理所有资源。
无论你是否等待,它都会这样做。因此,您无需等待,只要在您确信不会提交新任务时调用shutdown()
,其余内容将尽快发生。
答案 1 :(得分:1)
它说:
除了努力尝试停止处理之外,没有任何保证 积极执行任务。例如,典型的实现方式 通过Thread.interrupt()取消,因此任何无法响应的任务 中断可能永远不会终止。
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html#shutdownNow()
所以请改用awaitTermination。对于花费时间的线程,使用布尔变量作为volatile并检查它是否设置在外部。如果设置然后退出等等
答案 2 :(得分:0)
try {
executor = Executors.newSingleThreadExecutor();
future = executor.submit(task);
executor.shutdown();
executor.awaitTermination(5, TimeUnit.SECONDS);
}
finally {
if (Objects.nonNull(executor) && !executor.isTerminated()) {
LOGGER.error("cancelling all non-finished tasks");
}
if (Objects.nonNull(executor)) {
executor.shutdownNow();
LOGGER.info("shutdown finished");
}
}
这样你关闭执行器并等待5秒钟完成所有任务,最后调用executor.shutdownNow()
完全杀死执行者。
这是关闭执行程序的最佳方法。