【问题标题】:Confusion on Thread setDeaemon in javajava中线程setDaemon的困惑
【发布时间】:2011-04-19 08:18:02
【问题描述】:

根据java当setDaemon设置为true时

它不会阻止 JVM 程序完成时退出但 线程仍在运行。一个 守护程序线程的示例是 垃圾回收。

从下面的代码示例中,主线程创建的线程在setDaemon设置为true时停止执行,实际上它应该继续运行。当setDaemon 设置为 false 时,即使主线程退出,子线程也会打印 i 的值。 请澄清我的疑问。

public class DeamonSample implements Runnable
{
      public void run()
      {
            try 
{
System.out.println("T1 started...");

                  for (int i=0;i<1000;i++)
                  {
                        TimeUnit.SECONDS.sleep(1);
                        System.out.print(i+" ");
                  }
            } 
            catch (InterruptedException e) 
            {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
            }
            finally
            {
                  System.out.println("T1 ended...");
            }

      }


      /**
      * @param args
      */
      public static void main(String[] args)
      {
            // TODO Auto-generated method stub
            System.out.println("Main Started...");
            System.out.println("Main Thread Type="+Thread.currentThread().isDaemon());
            DeamonSample deamonSample=new DeamonSample();
            Thread t1=new Thread(deamonSample);
            t1.setDaemon(true);
            t1.start();
            System.out.println("T1 Type="+t1.isDaemon());
            System.out.println("Main Thread Type="+Thread.currentThread().isDaemon());
            System.out.println("Main ended...");
      }

}

【问题讨论】:

    标签: java multithreading


    【解决方案1】:

    默认情况下线程不是守护线程。如果您使用任何不是守护程序的线程到达主线程的末尾,那么该进程将继续运行。通过调用setDaemon(true),您是在告诉 JVM,您的线程不应在 main 结束时阻塞关闭。

    【讨论】:

      【解决方案2】:

      t1.setDaemon(true); 执行时,DeamonSample 实例肯定不会停止;你看到的不确定性来自打印。字符在合并到单个流之前被写入线程本地缓冲区。

      这里有一些代码来说明。两个线程轮流递增计数器并打印其状态,但您看到的数字可能非常乱。

      import java.util.concurrent.atomic.AtomicInteger;
      
      public class FunnyPrinter extends Thread {
          static AtomicInteger counter = new AtomicInteger(0);
      
          int parity;
      
          public FunnyPrinter(int parity) {
              super();
              this.parity = parity;
          }
      
          public void run() {
              for (;;)
                  if (counter.intValue() % 2 == parity)
                      System.out.println(counter.incrementAndGet());
          }
      
          public static void main(String[] args) {
              FunnyPrinter t1 = new FunnyPrinter(0), t2 = new FunnyPrinter(1);
              t1.start(); t2.start();
          }
      }
      

      如果您需要确定性,请在块结束前同步 System.outflush

      【讨论】:

        【解决方案3】:

        从下面的代码示例中,主线程创建的线程在 setDaemon 设置为 true 时停止执行

        这不会发生。再次检查您的输出。您的输出将包含以下几行:

        主要开始...
        主线程类型=false
        T1 类型=true
        主线程类型=false
        主要结束...

        ..实际上它应该继续运行。

        作为一个守护线程,它不会。由于所有非守护线程(主线程)都已完成,jvm 将退出。

        当 setDaemon 设置为 false 时,即使主线程退出,子线程也会打印 i 的值。请澄清我的疑问。

        正确

        【讨论】:

          【解决方案4】:

          在您的守护线程打印出所有数字之前,主线程终止... 如果你的新线程isDaemon = true,启动线程后试试这行():

          ...
          Thread t1=new Thread(deamonSample);
          try{
             t1.join();
          }catch(InterruptedException ie){
              ie.printStackTrace();
          }
          ...
          

          您会看到,守护线程将结束...(至少,这不再是多线程,但该示例仅用于说明目的)

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2019-02-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-09-27
            • 2012-06-16
            • 1970-01-01
            相关资源
            最近更新 更多