【问题标题】:Does it possible in java that daemon thread continue after main thread exited? [duplicate]在java中,主线程退出后守护线程是否可能继续? [复制]
【发布时间】:2012-01-12 10:23:12
【问题描述】:

我有在 Eclipse 嵌入式 Tomcat 中运行的多线程 Web 应用程序。有些线程是守护进程,有些不是。 在我跑完之后:

shutdown.bat

我看到一些线程完成了工作,但有些仍然存在!奇怪的是,剩余线程中是守护线程(我在 Eclipse 的调试视图中看到过)。但这是不可能的——我没有看到主线程,但看到了守护线程!它是否链接到特定的 Tomcat Web 容器,或者它可能是我的 Web 应用程序的问题? 谢谢。 或者它特定于 Eclipse 嵌入式 Tomcat?

【问题讨论】:

    标签: java multithreading daemon


    【解决方案1】:

    是的。当所有非守护线程都完成时,程序退出。如果 main 启动了一个正在运行的非守护线程,那么让名为“main”的线程退出不会做任何事情。

    【讨论】:

    • 但可能问题是关于我在调试器中看到的情况 - 我没有看到主线程,但可以看到守护进程(也作为非守护进程)。线程总数减少了 50% 附近。
    • 即使是一个非守护线程(可能是由一个未将线程标记为守护进程的库启动的)也会让程序继续运行。
    • 我的问题(请阅读标题)关于与文档的矛盾 - 其中说没有主线程就不能存在守护线程。
    • @user710818:阅读彼得的回答。你的假设是错误的。当有至少 1 个非守护线程正在运行时,守护线程会继续运行。主线程是否完成无关紧要。阅读docs.oracle.com/javase/6/docs/api/java/lang/…
    • @user710818 名为“main”的线程没有什么特别之处,只是它是为您运行程序而启动的。退出时也没有什么特别的事情发生。当最后一个非守护线程退出时,您的程序开始关闭。
    【解决方案2】:

    这是一个简单的证明。如果所有非主线程都是守护进程,一旦主线程死亡,它们就会全部死亡:

    class DaemonTask implements Runnable {
    
      private final int id;
      private final Thread main;
    
      DaemonTask(int id, Thread main) {
    
        this.id = id;
        this.main = main;
      }
    
      @Override
      public void run() {
    
        while (true) {
    
          System.out.println((Thread.currentThread().isDaemon() ? "" : "non") + " daemon id = " + id + "; main alive: " + main.isAlive());
          try {
            Thread.sleep(100L * id);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      }
    }
    
    for (int i = 0; i < 10; i++) {
    
      Thread t = new Thread(new DaemonTask(i + 1, Thread.currentThread()));
      t.setDaemon(true);
      t.start();
    }
    
    System.out.println("main finishing");
    

    有输出:

    main finishing
     daemon id = 6; main alive: true
     daemon id = 3; main alive: true
     daemon id = 2; main alive: true
     daemon id = 10; main alive: true
     daemon id = 9; main alive: false
     daemon id = 8; main alive: false
     daemon id = 4; main alive: false
    Process finished with exit code 0
    

    如果我们在离开主线程之前创建并启动一个非守护线程:

    new Thread(new DaemonTask(100, Thread.currentThread())).start();
    

    应用程序将继续运行:

    main finishing
     daemon id = 2; main alive: true
     daemon id = 1; main alive: true
     daemon id = 3; main alive: false
     daemon id = 4; main alive: false
     daemon id = 5; main alive: false
     daemon id = 7; main alive: false
     daemon id = 6; main alive: false
    non daemon id = 100; main alive: false
     daemon id = 10; main alive: false
     daemon id = 9; main alive: false
     daemon id = 8; main alive: false
     daemon id = 1; main alive: false
     daemon id = 2; main alive: false
     daemon id = 1; main alive: false
     daemon id = 3; main alive: false
     daemon id = 1; main alive: false
     daemon id = 4; main alive: false
     daemon id = 2; main alive: false
    

    【讨论】:

      【解决方案3】:

      您正在运行一个调试器,这基本上意味着 JVM 终止的行为不像预期的那样。

      开发人员很可能希望在 JVM 终止时检查守护线程。

      这意味着调试器实际上是应用程序中的“主”线程,并且调试器不希望将其内部工作暴露给 UI。想象一下在调试器代码本身中设置一个断点...我认为这可能会使事情有些混乱,因为您会锁定调试会话!

      如果您不使用调试器,请不要指望会发生这种情况。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-09-08
        • 2014-03-17
        • 1970-01-01
        • 1970-01-01
        • 2016-11-01
        • 2013-03-06
        • 1970-01-01
        相关资源
        最近更新 更多