发布日期:2018-03-26
如何正确停止Java中的线程?+ 查看更多
如何正确停止Java中的线程?
+ 查看更多
发布日期:2018-02-23 16:36
分类:JAVA
浏览次数:123
我需要一个解决方案来正确地停止线程在Java。
我有IndexProcessorclass实现Runnable接口:
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类启动和停止线程:
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。所以问题是:
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();方法,因为它已被弃用。
回答:
在IndexProcessor类中,您需要一种设置标志的方法,通知线程需要终止它,类似于您在类范围中使用的变量运行。
当你想停止线程,你设置这个标志,并调用join()线程,并等待它完成。
通过使用volatile变量或使用与用作标志的变量同步的getter和setter方法,确保该标志是线程安全的。
public class IndexProcessor implements Runnable { private static final Logger LOGGER = LoggerFactory.getLogger(IndexProcessor.class); private volatile boolean running = true; public void terminate() { running = false; } @Override public void run() { while (running) { try { LOGGER.debug("Sleeping..."); Thread.sleep((long) 15000); LOGGER.debug("Processing"); } catch (InterruptedException e) { LOGGER.error("Exception", e); running = false; } } } }
然后在SearchEngineContextListener:
public class SearchEngineContextListener implements ServletContextListener { private static final Logger LOGGER = LoggerFactory.getLogger(SearchEngineContextListener.class); private Thread thread = null; private IndexProcessor runnable = null; @Override public void contextInitialized(ServletContextEvent event) { runnable = new IndexProcessor(); thread = new Thread(runnable); 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) { runnable.terminate(); thread.join(); LOGGER.debug("Thread successfully stopped."); } } }