在Tomcat中,我编写了一个ServletContextListener,它将在启动时启动ExecutorService,并在卸载时终止它。
我正在关注ExecutorService
的javadoc中的示例public void contextDestroyed( ServletContextEvent sce )
{
executor.shutdown();
try
{
executor.awaitTermination( 50, TimeUnit.SECONDS );
}
catch( InterruptedException ie )
{
Thread.currentThread().interrupt();
}
}
我的问题是我应该在contextDestroyed()方法中传播InterruptedException吗?
答案 0 :(得分:5)
我会说不。容器调用contextDestroyed
方法作为上下文即将被拆除的通知,它不会征求您的许可。此外,Javadoc没有定义如果从中抛出异常会发生什么,因此结果可能是不可预测的和/或不可移植的。
我要做的是在catch区域内调用executor.shutdownNow()
来强行终止执行者(即“你有机会,现在停止”)。
答案 1 :(得分:1)
您的代码示例中包含的内容(重新中断当前线程)正是我所建议的。在你自己的代码之外的Tomcat中的某些东西发送了原始中断,所以让Tomcat有机会处理它。
我不知道Tomcat会对InterruptedException做什么。这是未定义的。但Tomcat发起了中断,Tomcat拥有了contextDestroyed(...)方法运行的线程。这里适用的“Java Concurrency in Practice”的一般原则是:线程的创建者负责处理线程生命 - 圆筒问题。
处理中断绝对是一个生命周期问题。
答案 2 :(得分:0)
我同意Steve的意见,重置中断标志会让控制之外的代码有机会对事件做出反应。
tempus-fugit提供了一种为您执行此操作的方法,以及如果事情花费太长时间的显式超时异常。
waitOrTimeout(shutdown(executor), timeout);
如果感兴趣的话,请查看文档的并发部分... tempusfugitlibrary.org/documentation
此example演示了它的用法,包括等待完成和更积极的关闭。