1.如下代码:

package com.bawei.multithread;

public class Recursive {

	private static int counter = 0;

	public static void main(String[] args) {
Thread t = new Thread(){
@Override
public void run() {
try {
//Thread-0线程
System.out.println(Thread.currentThread().getName()+" running");
Thread.sleep(100000);
System.out.println(Thread.currentThread().getName()+" done");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
t.start();
try {
Thread.sleep(50000);
//mian线程
System.out.println(Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
} }
}

当大家运行这段代码的时候,可以通过JDK安装的bin目录下的jconsole工具来查看,当前运行的线程,如下所示:

从这里大家可以看到程序当前运行的线程是main线程和Thread-0线程!

这里可以看到当我们的main线程执行完毕之后,我们的应用程序并没有推出,这是为什么呢?这是因为此时我们的应用程序还有活跃线程Thread-0!

如果我们对程序做一点改动,给线程Thread-0对象设置一个参数即:t.setDaemon(true);此时如果我的main线程结束之后,那么创建的main线程创建的守护线程的生命周期也就跟着结束了!代码如下所示:

package com.bawei.multithread;

public class Recursive {

	private static int counter = 0;

	public static void main(String[] args) {
Thread t = new Thread(){
@Override
public void run() {
try {
//Thread-0线程
System.out.println(Thread.currentThread().getName()+" running");
Thread.sleep(100000);
System.out.println(Thread.currentThread().getName()+" done");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
t.setDaemon(true);
t.start();
try {
Thread.sleep(50000);
//mian线程
System.out.println(Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

而且这里有一点需要特别注意:t.setDaemon(true); 一定要设置在t.start()之前,否则也会报错!

那这个Daemon线程有什么用处呢?

比如在我们建立网络连接的时候,例如从A到B我们建立了一个长连接,大家都知道长连接是要发心跳的,无论是每隔3秒,30秒,1分钟,这个时间是由你自己设置的,然后每隔这段时间客户端就往服务器端发一个心跳包,这样就可以知道对方的存在,就知道对方是可用的,如果不可用可能就需要重新发送连接请求!如果当前线程创建好了一个连接之后,除了利用这个连接通信之外,我还要维护一个心跳,这个心跳和业务逻辑,和通信是没关系的,这个心跳只不过是做维护的一个东西,那这个时候我把创建连接之后的这个线程开辟一个daemon线程,我创建这个daemon线程的目的就是做心跳检查(healthcheck),那这个有什么好处呢?如果我们不这么做,可能建立连接的线程已经死了,但是你的这个维护线程并不会死,必须你去通知它,或者手动关掉该维护线程,但是用stop方法关闭的时候,我们可能也是关闭不了的,因为这个方法已经被弃用了,而且此时如果你的维护线程不关闭,那么你整个应用程序(application)的进程就无法关闭,因为有活活动的线程,如果我们这里将这个维护的线程设置为通信线程的守护线程,那就很好解决了,此时一旦通信线程死掉,那维护线程自然就该挂了,所以守护线程可以帮我们做一些辅助性的东西!

setDaemon()方法默认是设置为false的!

我这里有两个问题,就是这里的Thread-0线程是一个守护线程,如果我在Thread-0这个线程中再开辟一个线程,然后将新开辟的线程也设置为守护线程,

第一:当Thread-0线程关闭的时候,这个新开辟的线程会关掉么?

1.当Thread-0不是守护线程的时候,如果Thread-0执行完毕之后,Thread-0创建的新守护线程会退出么,也就是整个应用程序会结束么?答案是会的,如下代码:

package com.bawei.multithread;

public class Recursive {

	private static int counter = 0;

	public static void main(String[] args) {
//新线程对象
Thread t = new Thread(){
@Override
public void run() {
//在新线程里面又创建了一个新的线程对象,
Thread innerThread = new Thread(){
@Override
public void run() {
try {
Thread.sleep(100*1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}; try {
innerThread.setDaemon(true);
innerThread.start();
Thread.sleep(10*1000);
System.out.println("外层t线程休息好了");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};//thread-0 end!
t.start(); }
}

从上面的运行代码可以看出,如果t线程结束之后,t线程创建的守护线程也会结束!

如果我们这里进一步将t线程也设置为守护线程,当main线程结束的时候,t线程毫无疑问会退出,那么t线程创建的新守护线程会退出么?也就是整个应用程序会随着main线程的结束而结束么?答案也是会的。看如下代码演示:

package com.bawei.multithread;

public class Recursive {

	private static int counter = 0;

	public static void main(String[] args) {
//新线程对象
Thread t = new Thread(){
@Override
public void run() {
//在新线程里面又创建了一个新的线程对象,
Thread innerThread = new Thread(){
@Override
public void run() {
try {
Thread.sleep(100*1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}; try {
innerThread.setDaemon(true);
innerThread.start();
Thread.sleep(10*1000);
System.out.println("外层t线程休息好了");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};//thread-0 end!
t.setDaemon(true);
t.start();
System.out.println("main线程结束了");
}
}

所以综上所述:只要是父线程死掉之后,守护线程都会立即死掉!整个应用程序也就结束了!

如果我们这里将t.setDaemon设置为false,也就是默认情况,那么当main线程死掉的时候,实际上子线程就不会死掉了,因为此时的子线程不是守护线程!

package com.bawei.multithread;

public class Recursive {

	private static int counter = 0;

	public static void main(String[] args) {
//新线程对象
Thread t = new Thread(){
@Override
public void run() {
//在新线程里面又创建了一个新的线程对象,
Thread innerThread = new Thread(){
@Override
public void run() {
try {
Thread.sleep(100*1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} }; try {
innerThread.setDaemon(true);
innerThread.start();
Thread.sleep(10*1000);
System.out.println("外层t线程休息好了");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};//thread-0 end!
//t.setDaemon(true);
t.start();
System.out.println("main线程结束了");
}
}

 运行一下可以看到,如果main线程死掉,此时的t线程也不会挂掉!

第二个问题是如果Thread-0线程执行完毕、main线程也执行完毕,那么整个应用程序(application)会结束么?

我们这里验证一下:

6.Daemon线程的更多相关文章

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

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

  2. java concurrency: daemon线程

    daemon线程的概念 在学习操作系统概念的时候,我们就曾听说过daemon的概念.daemon本身指的是在后台运行的进程或者线程,一般用来提供某些不需要与用户直接交互的服务,有点像我们见到的一些系统 ...

  3. [Python]Threading.Thread之Daemon线程

    之前对Daemon线程理解有偏差,特记录说明: 一.什么是Daemon A thread can be flagged as a "daemon thread". The sign ...

  4. python之daemon线程

    [python之daemon线程] A thread can be flagged as a “daemon thread”. The significance of this flag is tha ...

  5. java线程基础知识----java daemon线程

    java线程是一个运用很广泛的重点知识,我们很有必要了解java的daemon线程. 1.首先我们必须清楚的认识到java的线程分为两类: 用户线程和daemon线程 A. 用户线程: 用户线程可以简 ...

  6. Java 学习笔记之 Daemon线程

    Daemon线程: 线程: 用户线程 守护线程 守护线程是一种特殊的线程,在进程中不存在非守护线程了,则守护线程自动销毁. public class DaemonThread extends Thre ...

  7. java线程基础巩固---Daemon线程的创建以及使用场景分析

    daemon线程既守护线程,而在jdk中对于Thread中针对守护线程有专门的API,如下: 而之前在公司项目中就看到过有人使用过Thread中的这个API,但是对于它的使用场景完全不知,所以这次好好 ...

  8. 什么是 Daemon 线程?它有什么意义?

    所谓后台(daemon)线程,是指在程序运行的时候在后台提供一种通用服务的线 程,并且这个线程并不属于程序中不可或缺的部分.因此,当所有的非后台线程 结束时,程序也就终止了,同时会杀死进程中的所有后台 ...

  9. JAVA DAEMON线程的理解

    java线程分两种:用户线程和daemon线程.daemon线程或进程就是守护线程或者进程,但是java中所说的daemon线程和linux中的daemon是有一点区别的. linux中的daemon ...

随机推荐

  1. python多线程相关知识点

    1. 信号量 信号机维护着一个计数器,指定可同时访问资源或者进入临界区的线程数.每次有一个线程获得信号机时,计数器-1.若计数器为0,其他线程就停止访问信号机 Semphore,是一种带计数的线程同步 ...

  2. 剑指Offer题解(Python版)

    https://blog.csdn.net/tinkle181129/article/details/79326023# 二叉树的镜像    链表中环的入口结点    删除链表中重复的结点    从尾 ...

  3. 【socket-python应用】控制泓格ET-7044通信模块输入DI输出DO

    socket-python应用:控制泓格ET-7044通信模块输入DI输出DO 本节主要内容: 1.socket-python建立TCP通信 2.配合泓格通信模块说明书,查看输入输出寄存器地址,发送指 ...

  4. MVVM软件设计模式(转)

    add by zhj: MVVM是一种软件设计模式,这里要说一下设计模式,我们通常所的设计模式是指面向对象中的设计模式,用在面向对象编程语言中.但软件设计模式是更高一个级别的设计模式,两者不是同一个东 ...

  5. js判断开始时间不能小于结束时间

    function validTime(startTime,endTime){ var arr1 = startTime.split("-");       var arr2 = e ...

  6. Requirejs 使用

    代码地址 参考地址1 参考地址2 一.不依赖其他模块的module创建 创建math的module // math.js define(function (){ var add = function ...

  7. Could not autowire. No beans of 'TbItemMapper' type found. less... (Ctrl+F1) Checks autowiring prob

    Intellij Idea开发工具在@Autowired或者@Resource注入XxxMapper接口时报如下错误: Could not autowire. No beans of 'TbItemM ...

  8. Linux dmidecode 命令

    当我们需要获取机器硬件信息时,可使用linux系统自带的dmidecode工具进行查询. dmidecode 用于获取服务器的硬件信息,通常是在不打开计算机机箱的情况下使用该命令来查找硬件详细信息 这 ...

  9. 前端 HTML body标签相关内容

    想要在网页上展示出来的内容一定要放在body标签中. 常用标签: 标题标签 h1-h6 段落标签 p标签 超链接标签 a标签 列表标签 ul,ol,li 定义列表<dl> 子标签 div ...

  10. K-means &K-medoids 聚类

    k-平均值算法对孤立点很敏感!因为具有特别大的值的对象可能显著地影响数据的分布. k-中心点(k-Medoids): 不采用簇中对象的平均值作为参照点, 而是选用簇中位置最中心的对象, 即中心点(me ...