【问题标题】:Stopping a thread in a Tomcat Application - which method?停止 Tomcat 应用程序中的线程 - 哪种方法?
【发布时间】:2013-01-31 19:37:35
【问题描述】:

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

  1. MyConsumer.java的try语句中是否必须要有Thread.sleep()?
  2. 不检查我的布尔标志running,我是否应该删除标志的概念而只检查while(!Thread.currentThread().isInterrupted)

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);
            }
        }
    }
}

MyConsumer.java:

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;
                }
            }

    }

【问题讨论】:

    标签: java multithreading apache tomcat


    【解决方案1】:

    MyConsumer.java的try语句中是否必须要有Thread.sleep()

    没有。我认为 sleep 调用是为了确保 doStuff() 在每次调用之间以 1 秒的间隔执行,而不是连续执行。如果你想要这个 1 秒的间隔,你需要把睡眠电话留在那里。如果你想让doStuff()连续执行,那么你需要去掉sleep。

    我应该删除标志的概念并只检查 while(!Thread.currentThread().isInterrupted),而不是检查我的布尔标志,运行吗?

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

    【讨论】:

    • 非常感谢。因此,在我的 contextDestroyed() 中,我将添加对 thread.interrupt() 的调用。我还需要在 thread.interrupt() 之前调用 thread.join() 吗?
    • 另外,应该从 contextDestroyed() 调用 thread.interrupt(),还是从 MyConsumer 类中的 catch (InterruptedException ex) 块调用?
    • 为了抛出 InterruptedException 必须中断线程。所以你需要从 contextDestroyed() 方法调用 interrupt() 。并且中断要求线程中断自己,并立即返回。因此,如果您想等待线程终止后再从 contextDestroyed() 返回,您仍然需要加入调用。
    • 再次感谢您的帮助。
    【解决方案2】:

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

    关于布尔running标志,它提供了类似中断的功能,只是它不是由抛出InterruptedException的方法触发的。根据在这些方法中停止正常操作流程是否有意义,您应该使用其中一种机制,但不能同时使用两种机制。

    请参阅http://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html,了解如何使用中断的详细概述。

    【讨论】:

      猜你喜欢
      • 2013-05-02
      • 1970-01-01
      • 2012-03-29
      • 1970-01-01
      • 2016-08-31
      • 1970-01-01
      • 2016-05-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多