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.

下面是示例代码:

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

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

  1. dt is a daemon thread.
  2. Sleeping in main thread.
  3. ..........
  4. Main thread ending.

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

  1. Sleeping in main thread.
  2. ..........
  3. Main thread ending.
  4. .......................

设置daemon线程的意义

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

daemon线程的一些应用

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

又一个daemon的示例

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

具体的代码实现如下:

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

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

  1. Reminder set for 10/21/12 01:57:10 PM
  2. ..
  3. Call Harry
  4. ..................
  5. Main thread ending.

总结

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

java concurrency: daemon线程的更多相关文章

  1. 【转】关于Java的Daemon线程的理解

    原文地址:http://www.cnblogs.com/ChrisWang/archive/2009/11/28/1612815.html 关于Java的Daemon线程的理解 网上对Java的Dae ...

  2. 深入浅出 Java Concurrency (35): 线程池 part 8 线程池的实现及原理 (3)[转]

    线程池任务执行结果 这一节来探讨下线程池中任务执行的结果以及如何阻塞线程.取消任务等等. 1 package info.imxylz.study.concurrency.future;2 3 publ ...

  3. 深入浅出 Java Concurrency (34): 线程池 part 7 线程池的实现及原理 (2)[转]

    线程池任务执行流程 我们从一个API开始接触Executor是如何处理任务队列的. java.util.concurrent.Executor.execute(Runnable) Executes t ...

  4. 深入浅出 Java Concurrency (33): 线程池 part 6 线程池的实现及原理 (1)[转]

    线程池数据结构与线程构造方法 由于已经看到了ThreadPoolExecutor的源码,因此很容易就看到了ThreadPoolExecutor线程池的数据结构.图1描述了这种数据结构. 图1 Thre ...

  5. 深入浅出 Java Concurrency (30): 线程池 part 3 Executor 生命周期[转]

    我们知道线程是有多种执行状态的,同样管理线程的线程池也有多种状态.JVM会在所有线程(非后台daemon线程)全部终止后才退出,为了节省资源和有效释放资源关闭一个线程池就显得很重要.有时候无法正确的关 ...

  6. 深入浅出 Java Concurrency (28): 线程池 part 1 简介[转]

    从这一节开始正式进入线程池的部分.其实整个体系已经拖了很长的时间,因此后面的章节会加快速度,甚至只是一个半成品或者简单化,以后有时间的慢慢补充.完善. 其实线程池是并发包里面很重要的一部分,在实际情况 ...

  7. 深入浅出 Java Concurrency (36): 线程池 part 9 并发操作异常体系[转]

    并发包引入的工具类很多方法都会抛出一定的异常,这些异常描述了任务在线程池中执行时发生的例外情况,而通常这些例外需要应用程序进行捕捉和处理. 例如在Future接口中有如下一个API: java.uti ...

  8. 深入浅出 Java Concurrency (29): 线程池 part 2 Executor 以及Executors[转]

    Java里面线程池的顶级接口是Executor,但是严格意义上讲Executor并不是一个线程池,而只是一个执行线程的工具.真正的线程池接口是ExecutorService. 下面这张图完整描述了线程 ...

  9. Java Concurrency - 取消线程执行器中的线程

    When you work with an executor, you don't have to manage threads. You only implement the Runnable or ...

随机推荐

  1. halcon与C#混合编程

    halcon源程序: dev_open_window(0, 0, 512, 512, 'black', WindowHandle)read_image (Image, 'C:/Users/BadGuy ...

  2. [C++]Saving the Universe——Google Code Jam Qualification Round 2008

    Google Code Jam 2008 资格赛的第一题:Saving the Universe. 问题描述如下: Problem The urban legend goes that if you ...

  3. HDU 5274 Dylans loves tree(树链剖分)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5274 [题目大意] 给出一棵树,每个点有一个权值,权值可修改,且大于等于0,询问链上出现次数为奇数 ...

  4. 利用路由器搭建受限wifi热点,气死蹭网的坏人~

    很多人的无线路由器都设密码,不在家的时候还会关了,一点互联网分享的精神都没有.我就一直开着无线路由器,也从不设密码,让周围的人可以搜到我的信号,连接成功,我就会很开心.虽然我没有装宽带,但我觉得这已经 ...

  5. oracle rac ha

    ha,仅只是在操作系统层面进行数据库的监控和管理,一般只针对单实例数据库使用.优点是管理方便,应用开发方便(方便了开发商):工程投入较小.缺点是,具有所有单实例数据库的缺点:如:容错能力差,续航能力差 ...

  6. How to get the xpath by clicking an html element

    How to get the xpath by clicking an html element How to get the xpath by clicking an html element

  7. Tomcat从零开始(十)Loader

    第十课: 不知不觉就10篇blog了,说实话,我是第一次更这么长时间的Blog. 嗯,今天说说Loader,在以前的课程中,也就是内个能使用最初级的servlet的那一节,我们使用了URLClassL ...

  8. hdu 4105 贪心思想

    淋漓尽致的贪心思想 波谷一定是一位数.波峰一位数不够大的时候加入到两位数就一定够大了的. 当在寻找波谷碰到零了就自然当成波谷. 当在寻找波峰时碰到零时,将前面的波谷加到前一个波峰上.让当前的零做波谷, ...

  9. 如何在windows server 2012 R2 部署WEB项目

    tip: 今天发布项目到windows server 2012 R2上面. 没有接触过,其实很简单,看图: 这是安装IIS成功后显示的总图: 二.点击Manage ,选择Add Roles and F ...

  10. js字面量

    以前一直对js字面量模棱两可. '字面量是一种表示值的记法.' js字面量(literal) 分为以下几个 number literal        8   就是数字字面量 string liter ...