我需要一个解决方案来正确停止 Java 中的线程。
我有实现 Runnable 接口(interface)的 IndexProcessor
类:
public class IndexProcessor implements Runnable {
private static final Logger LOGGER = LoggerFactory.getLogger(IndexProcessor.class);
@Override
public void run() {
boolean run = true;
while (run) {
try {
LOGGER.debug("Sleeping...");
Thread.sleep((long) 15000);
LOGGER.debug("Processing");
} catch (InterruptedException e) {
LOGGER.error("Exception", e);
run = false;
}
}
}
}
我有 ServletContextListener
类来启动和停止线程:
public class SearchEngineContextListener implements ServletContextListener {
private static final Logger LOGGER = LoggerFactory.getLogger(SearchEngineContextListener.class);
private Thread thread = null;
@Override
public void contextInitialized(ServletContextEvent event) {
thread = new Thread(new IndexProcessor());
LOGGER.debug("Starting thread: " + thread);
thread.start();
LOGGER.debug("Background process successfully started.");
}
@Override
public void contextDestroyed(ServletContextEvent event) {
LOGGER.debug("Stopping thread: " + thread);
if (thread != null) {
thread.interrupt();
LOGGER.debug("Thread successfully stopped.");
}
}
}
但是当我关闭 tomcat 时,我的 IndexProcessor 类中出现异常:
2012-06-09 17:04:50,671 [Thread-3] ERROR IndexProcessor Exception
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at lt.ccl.searchengine.processor.IndexProcessor.run(IndexProcessor.java:22)
at java.lang.Thread.run(Unknown Source)
我使用的是 JDK 1.6。所以问题是:
如何停止线程而不抛出任何异常?
P.S.我不想使用 .stop();
方法,因为它已被弃用。
使用 Thread.interrupt()
是一种完全可以接受的方式。事实上,它可能比上面建议的标志更可取。原因是如果你在一个可中断的阻塞调用中(比如 Thread.sleep
或使用 java.nio Channel 操作),你实际上可以立即摆脱这些。
如果使用标志,则必须等待阻塞操作完成,然后才能检查标志。在某些情况下,您无论如何都必须这样做,例如使用不可中断的标准 InputStream
/OutputStream
。
在这种情况下,当线程被中断时,它不会中断 IO,但是,您可以轻松地在代码中常规执行此操作(并且您应该在可以安全停止和清理的关键点执行此操作)
if (Thread.currentThread().isInterrupted()) {
// cleanup and stop execution
// for example a break in a loop
}
就像我说的那样,Thread.interrupt()
的主要优点是您可以立即中断可中断的调用,而标志方法无法做到这一点。
我是一名优秀的程序员,十分优秀!