我有这个测试代码:
ExecutorService executor = Executors.newFixedThreadPool(3);
executor.execute(new Runnable() {
@Override
public void run() {
try {
System.out.println("run begins");
Thread.sleep(1000);
System.out.println("run ends");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
try {
executor.awaitTermination(0L, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
executor.shutdown();
System.out.println("-----------");
我期望,因为Runnable应该休眠15秒然后结束,然后executor等待它的终止和关闭,最后,执行System.out.println("-----------");
。
但实际输出是:
-----------
run begins
run ends
执行顺序对我来说没有多大意义。似乎是ExecutorService。awaitXXX和shutdown()不会阻塞主线程。System.out.println("-----------");
是要打印的第一行代码,然后是Runnable代码。
这是设计的行为吗?
如果是,那么我的问题是:如果awaitXXXX方法不阻塞主线程,主线程如何知道何时ExecutorService
完成?
似乎是ExecutorService。awaitXXX和shutdown()不会阻塞主线程
方法awaitTermination()
does阻塞调用线程,但是您指定了0
秒的超时时间。引用自javadoc:
阻塞,直到所有任务在关机请求后完成执行,或者超时发生,或者当前线程被中断,以先发生的为准。
如果你期望awaitTermination()
会中断提交的任务,那么你的期望是错误的,它不会这样做。此方法只允许您指定等待的时间段,并报告executor是否完成。
的回报:如果此执行器终止,则为True;如果在终止前超时,则为false
方法shutdown()
也将不中断任何先前提交的任务:
启动有序关机,其中先前提交的任务将被执行,但不接受新任务。
如果您想尝试中断已提交的任务,请使用shutdownNow()
。
尝试停止所有正在执行的任务,停止正在等待的任务的处理,并返回正在等待执行的任务列表。
注意:使用shutdown()
是首选的方法。
From Javadocs ofExecutorService#awaitTermination
:
阻塞直到所有任务完成执行之后的一个关机请求
这意味着awaitTermination
只会在关机请求后工作,所以你需要在awaitTermination()
之前调用shutdown()
。
此外,正如@Alexander Ivanchenko提到的另一个答案,设置timeout为0L将不会等待任何东西,awaitTermination
通过返回值指示线程是否及时终止。如果主线程被另一个线程中断,则抛出InterruptedException
。