Java 停止Tomcat应用程序中的线程-哪种方法?

Java 停止Tomcat应用程序中的线程-哪种方法?,java,multithreading,apache,tomcat,Java,Multithreading,Apache,Tomcat,我使用下面的实现来停止Tomcat中的线程。代码是有效的,但我想知道两件事: 是否有必要在MyConsumer.java的try语句中包含Thread.sleep() 我是否应该在(!Thread.currentThread().isInterrupted)时删除标志的概念并只检查,而不是检查布尔标志,running ServletContextListener: public final class ApplicationListener implements ServletContextLi

我使用下面的实现来停止Tomcat中的线程。代码是有效的,但我想知道两件事:

  • 是否有必要在MyConsumer.java的try语句中包含Thread.sleep()
  • 我是否应该在(!Thread.currentThread().isInterrupted)时删除标志的概念并只检查
    ,而不是检查布尔标志,
    running
    ServletContextListener:

    public final class ApplicationListener implements ServletContextListener {
    
        private Thread thread = null;
        private MyConsumer k = null;
    
        public ApplicationListener() {
        }
    
        @Override
        public void contextInitialized(ServletContextEvent event) {
    
            k = new MyConsumer();
            thread = new Thread(k);
    
            thread.start();
    
        }
    
        @Override
        public void contextDestroyed(ServletContextEvent event) {
            if (thread != null) {
                k.terminate();
                try {
                    thread.join();
                } catch (InterruptedException ex) {
                    Logger.getLogger(ApplicationListener.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
    }
    
    public class MyConsumer implements Runnable {
    
        private volatile boolean running = true;
    
        public MyConsumer() {
        }
    
        public void terminate() {
            running = false;
        }
    
        @Override
        public void run() {
    
                while (running) {
    
                    try {
    
                        doStuff();
                        Thread.sleep((long) 1000);
    
                    } catch (InterruptedException ex) {
                        Logger.getLogger(MyConsumer.class.getName()).log(Level.SEVERE, null, ex);
                        running = false;
                    }
                }
    
        }
    
    MyConsumer.java:

    public final class ApplicationListener implements ServletContextListener {
    
        private Thread thread = null;
        private MyConsumer k = null;
    
        public ApplicationListener() {
        }
    
        @Override
        public void contextInitialized(ServletContextEvent event) {
    
            k = new MyConsumer();
            thread = new Thread(k);
    
            thread.start();
    
        }
    
        @Override
        public void contextDestroyed(ServletContextEvent event) {
            if (thread != null) {
                k.terminate();
                try {
                    thread.join();
                } catch (InterruptedException ex) {
                    Logger.getLogger(ApplicationListener.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
    }
    
    public class MyConsumer implements Runnable {
    
        private volatile boolean running = true;
    
        public MyConsumer() {
        }
    
        public void terminate() {
            running = false;
        }
    
        @Override
        public void run() {
    
                while (running) {
    
                    try {
    
                        doStuff();
                        Thread.sleep((long) 1000);
    
                    } catch (InterruptedException ex) {
                        Logger.getLogger(MyConsumer.class.getName()).log(Level.SEVERE, null, ex);
                        running = false;
                    }
                }
    
        }
    
    是否有必要在MyConsumer.java的try语句中包含Thread.sleep()

    不可以。我想,睡眠调用是为了确保每次调用之间间隔1秒执行
    doStuff()
    ,而不是连续执行。如果您想要这1秒的间隔,您需要将睡眠呼叫留在那里。如果要连续执行
    doStuff()
    ,则需要删除睡眠

    与其检查布尔标志running,不如删除标志的概念,只检查while(!Thread.currentThread().isInterrupted)


    是的,我确实会这么做。它将消除对标志的需要,并允许尽快停止线程,而不必等待睡眠调用在1秒后返回。另一个优点是,您可以检查
    doStuff()
    方法中的线程是否中断,以防它是一个长时间运行的方法,您希望尽快停止

    你的线程没有理由仅仅为了检查中断而休眠。您可以在那里调用Thread.interupted()

    关于boolean
    running
    标志,它提供了与interrupted类似的功能,只是它不是由抛出InterruptedException的方法触发的。根据停止这些方法中的正常操作流是否合理,您应该使用一种或另一种机制,但不能同时使用这两种机制


    有关如何使用中断的详细概述,请参阅。

    非常感谢。因此,在我的contextDestructed()中,我将添加对thread.interrupt()的调用。我是否仍然需要在thread.interrupt()之前调用thread.join()?另外,应该从contextDestroyed()调用thread.interrupt(),还是从MyConsumer类中的catch(InterruptedException ex)块调用thread.interrupt()?为了抛出eh InterruptedException,必须中断线程。因此,您需要从contextDestroyed()方法调用interrupt()。中断请求线程中断自身,并立即返回。因此,如果要等待线程终止后再从contextDestroyed()返回,则仍然需要加入调用。再次感谢您的帮助。