java concurrency: daemon线程

daemon线程的概念

        在学习操作系统概念的时候,我们就曾听说过daemon的概念。daemon本身指的是在后台运行的进程或者线程,一般用来提供某些不需要与用户直接交互的服务,有点像我们见到的一些系统服务。在java线程中,一般可以分为两类,一类是普通的线程,就是那些我们通过常用的Thread类或者Runnable接口实现并启动的类。还有一类是daemon线程。这种线程也通过和创建普通线程同样的方式来创建,不过需要通过setDaemon方法设置为daemon线程。

        daemon线程有几个典型的特征:

        1. daemon线程是运行于后台的,不和用户直接交互。

        2. 相对普通的线程来说,daeomn线程可以说是普通线程的下属,它的优先级要低一些。

        3. daemon线程具有一定程度的继承性,这个继承性不是指类的继承,而是指当一个daemon线程创建一个新线程的话,这个新创建的线程就默认为daemon线程了。

        4. 和普通线程的退出机制不同,在jvm即将关闭的时候,普通线程需要执行一系列的记录或者退出方法,比如需要执行finalize方法的则需要执行这部分,有finally块的代码也必须执行。而daemon线程退出的时候,jvm直接将它丢弃并退出,里面就算有finally块定义的代码也不会被执行。

 

一个daemon线程的示例

        创建或者使用daemon线程一般包括一下3个步骤:

1. 如果线程本身就是daemon线程了,那么通过常规线程创建手段创建出来的就已经是daemon线程。

2. 如果通过普通线程创建创建出来的话,需要在启动线程前调用setDaemon()方法。切记,一定要在调用start()方法前。

3.我们可以通过调用isDaemon()方法来判断一个线程是否为daeomn.

下面是示例代码:

 

Java代码  收藏代码
  1. class MyDaemon implements Runnable  
  2. {  
  3.     Thread thrd;  
  4.   
  5.     MyDaemon()  
  6.     {  
  7.         // Create the thread  
  8.         thrd = new Thread(this);  
  9.   
  10.         // Set to daemon  
  11.         thrd.setDaemon(true);  
  12.   
  13.         // Start the thread  
  14.         thrd.start();  
  15.     }  
  16.   
  17.     public void run()  
  18.     {  
  19.         try  
  20.         {  
  21.             for(;;)  
  22.             {  
  23.                 System.out.print(".");  
  24.                 Thread.sleep(1000);  
  25.             }  
  26.         }  
  27.         catch(InterruptedException exc)  
  28.         {  
  29.             System.out.println("MyDaemon interrupted.");  
  30.         }  
  31.     }  
  32. }  
  33.   
  34. class DaemonDemo  
  35. {  
  36.     public static void main(String[] args)  
  37.     {  
  38.         MyDaemon dt = new MyDaemon();  
  39.         if(dt.thrd.isDaemon())  
  40.             System.out.println("dt is a daemon thread.");  
  41.   
  42.         System.out.println("Sleeping in main thread.");  
  43.   
  44.         try  
  45.         {  
  46.             Thread.sleep(10000);  
  47.         }  
  48.         catch(InterruptedException exc)  
  49.         {  
  50.             System.out.println("Main thread interrupted.");  
  51.         }  
  52.   
  53.         System.out.println("\nMain thread ending.");  
  54.     }  
  55. }  

 在上面的代码中,我们实现Runnable接口定义一个MyDaemon类,在构造函数中调用setDaemon()设置该线程为daemon.在main方法中启动MyDaemon线程之后,main方法结束时daemon线程也自动结束了。上述代码的执行结果如下:

 

Java代码  收藏代码
  1. dt is a daemon thread.  
  2. Sleeping in main thread.  
  3. ..........  
  4. Main thread ending.  

 

一个比较有意思的事情就是,如果我们将前面代码里setDaemon()方法的这一行注释了,也就是说将该线程设置为普通的用户线程,再执行上面的代码时,我们会发现,程序不会终止,会一直执行下去,虽然主线程已经结束了。其输出的结果会像如下所示:

 

Java代码  收藏代码
  1. Sleeping in main thread.  
  2. ..........  
  3. Main thread ending.  
  4. .......................  

设置daemon线程的意义

        从前面的理解来看,daemon线程有点像一个我们画的草图,随时可以丢弃。它一般是用于在jvm关闭的时候,我们需要启动一些线程做一些辅助性的工作,但是我们又不希望这种工作妨碍到jvm正常关闭。和其他正常的线程来说,或许我们应该称之为不碍事的线程更合适。

daemon线程的一些应用

        daemon线程在java中有很多地方用到,一个典型的就是垃圾回收的GC线程。另外如果我们需要用线程做一些比如时间提醒,标记等事情,采用daemon线程也是一个比较合适的选择。

 

又一个daemon的示例

        根据前面的理解,我们再尝试一个更复杂的daemon应用。假定我们在一个应用中需要定义一些时间通知,比如说设置在某个指定的时候弹出一个会议通知的提醒。这是一个比较常见的场景,可以用daemon线程来实现。

具体的代码实现如下:

 

Java代码  收藏代码
  1. import java.util.*;  
  2.   
  3. class Reminder implements Runnable  
  4. {  
  5.     Calendar reminderTime;  
  6.   
  7.     String message;  
  8.   
  9.     Reminder(String msg, int delay)  
  10.     {  
  11.         message = msg;  
  12.           
  13.         // Get the current time and date.  
  14.         reminderTime = Calendar.getInstance();  
  15.   
  16.         // Add the delay to the time and date.  
  17.         reminderTime.add(Calendar.SECOND, delay);  
  18.   
  19.         System.out.printf("Reminder set for %tD %1$tr\n", reminderTime);  
  20.   
  21.   
  22.         // Create the reminder thread.  
  23.         Thread dThrd = new Thread(this);  
  24.   
  25.         // Set to daemon  
  26.         dThrd.setDaemon(true);  
  27.   
  28.         // Start execution.  
  29.         dThrd.start();  
  30.     }  
  31.   
  32.     // Run the reminder.  
  33.     public void run()  
  34.     {  
  35.         try  
  36.         {  
  37.             for(;;)  
  38.             {  
  39.                 // Get the current time and date.  
  40.                 Calendar curTime = Calendar.getInstance();  
  41.   
  42.                 // See if it's time for the reminder.  
  43.                 if(curTime.compareTo(reminderTime) >= 0)  
  44.                 {  
  45.                     System.out.println("\n" + message + "\n");  
  46.                     break;  
  47.                 }  
  48.   
  49.                 Thread.sleep(1000);  
  50.             }  
  51.         }  
  52.         catch(InterruptedException exc)  
  53.         {  
  54.             System.out.println("Reminder interrupted.");  
  55.         }  
  56.     }  
  57. }  
  58.   
  59. class ReminderDemo  
  60. {  
  61.     public static void main(String[] args)  
  62.     {  
  63.         // Get a reminder 2 seconds from now.  
  64.         Reminder mt = new Reminder("Call Harry", 2);  
  65.   
  66.         // Keep the main thread alive for 20 seconds.  
  67.         for(int i = 0; i < 20; i++)  
  68.         {  
  69.             try  
  70.             {  
  71.                 Thread.sleep(1000);  
  72.             }  
  73.             catch(InterruptedException exc)  
  74.             {  
  75.                 System.out.println("Main thread interrupted.");  
  76.             }  
  77.             System.out.print(".");  
  78.         }  
  79.   
  80.         System.out.println("\nMain thread ending.");  
  81.     }  
  82. }  

         我们设置了一个daemon线程,在一个无限循环里比较当前时间和指定的时间,在达到指定的时间时则显示一个提醒消息。上述代码的输出如下:

 

Java代码  收藏代码
  1. Reminder set for 10/21/12 01:57:10 PM  
  2. ..  
  3. Call Harry  
  4.   
  5. ..................  
  6. Main thread ending.  

总结

        悄悄的,daemon线程走了,正如daemon线程悄悄的来;挥一挥手,带不走jvm的一片云彩:)

posted @ 2016-08-13 22:27  googlemeoften  阅读(233)  评论(0编辑  收藏  举报