在Java中有两类线程:用户线程 (User Thread)、守护线程 (Daemon Thread)。

所谓守护 线程,是指在程序运行的时候在后台提供一种通用服务的线程,比如垃圾回收线程就是一个很称职的守护者,并且这种线程并不属于程序中不可或缺的部分。因 此,当所有的非守护线程结束时,程序也就终止了,同时会杀死进程中的所有守护线程。反过来说,只要任何非守护线程还在运行,程序就不会终止。

用户线程和守护线程两者几乎没有区别,唯一的不同之处就在于虚拟机的离开:如果用户线程已经全部退出运行了,只剩下守护线程存在了,虚拟机也就退出了。 因为没有了被守护者,守护线程也就没有工作可做了,也就没有继续运行程序的必要了。

将线程转换为守护线程可以通过调用Thread对象的setDaemon(true)方法来实现。在使用守护线程时需要注意一下几点:

(1) thread.setDaemon(true)必须在thread.start()之前设置,否则会跑出一个IllegalThreadStateException异常。你不能把正在运行的常规线程设置为守护线程。

(2) 在Daemon线程中产生的新线程也是Daemon的。

(3) 守护线程应该永远不去访问固有资源,如文件、数据库,因为它会在任何时候甚至在一个操作的中间发生中断。

代码示例:

import java.util.concurrent.TimeUnit

/**

 *  守护线程

 */

public class Daemons {

    /*

     * @param args

     * @throws InterruptedException

     */

    public static void main(String[] args) throws InterruptedException {

        Thread d = new Thread(new Daemon());

        d.setDaemon(true); //必须在启动线程前调用

        d.start();

        System.out.println("d.isDaemon() = " + d.isDaemon() + ".");

        TimeUnit.SECONDS.sleep(1);

    }

}

class DaemonSpawn implements Runnable {

    public void run() {

        while (true) {

            Thread.yield()

        }

    }

}

class Daemon implements Runnable {

    private Thread[] t = new Thread[10];

    public void run() {

        for (int i=0; i<t.length; i++) {

            t[i] = new Thread(new DaemonSpawn());

            t[i].start();

            System.out.println("DaemonSpawn " + i + " started.");

        }

        for (int i=0; i<t.length; i++) {

            System.out.println("t[" + i + "].isDaemon() = " +

                    t[i].isDaemon() + ".");

        }

        while (true) {

            Thread.yield();

        }

    }

}

运行结果:

d.isDaemon() = true.
DaemonSpawn 0 started
DaemonSpawn 1 started.
DaemonSpawn 2 started.
DaemonSpawn 3 started.
DaemonSpawn 4 started.
DaemonSpawn 5 started.
DaemonSpawn 6 started.
DaemonSpawn 7 started.
DaemonSpawn 8 started.
DaemonSpawn 9 started.
t[0].isDaemon() = true.
t[1].isDaemon() = true.
t[2].isDaemon() = true.
t[3].isDaemon() = true.
t[4].isDaemon() = true.
t[5].isDaemon() = true.
t[6].isDaemon() = true.
t[7].isDaemon() = true.
t[8].isDaemon() = true.
t[9].isDaemon() = true.

以上结果说明了守护线程中产生的新线程也是守护线程。

如果将mian函数中的TimeUnit.SECONDS.sleep(1);注释掉,运行结果如下:

d.isDaemon() = true.
DaemonSpawn 0 started.
DaemonSpawn 1 started.
DaemonSpawn 2 started.
DaemonSpawn 3 started.
DaemonSpawn 4 started.
DaemonSpawn 5 started.
DaemonSpawn 6 started.
DaemonSpawn 7 started.
DaemonSpawn 8 started.
DaemonSpawn 9 started.

以上结果说明了如果用户线程已经全部退出运行了,只剩下守护线程存在了,虚拟机也就退出了。下面的例子也说明了这个问题。

代码示例:

import java.util.concurrent.TimeUnit;

/**

 * Finally shoud be always run ?

 */

public class DaemonsDontRunFinally {
/**
* @param args
*/ public static void main(String[] args) { Thread t = new Thread(new ADaemon()); t.setDaemon(true); t.start(); }
} class ADaemon implements Runnable { public void run() {
try { System.out.println("start ADaemon..."); TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) {
System.out.println("Exiting via InterruptedException");
} finally {
System.out.println("This shoud be always run ?");
}
} }

运行结果:

start ADaemon...

如果将main函数中的t.setDaemon(true);注释掉,运行结果如下:

start ADaemon...

This shoud be always run ?

JAVA并发编程——守护线程(Daemon Thread)的更多相关文章

  1. java并发编程学习: 守护线程(Daemon Thread)

    在正式理解这个概念前,先把 守护线程 与 守护进程 这二个极其相似的说法区分开,守护进程通常是为了防止某些应用因各种意外原因退出,而在后台独立运行的系统服务或应用程序. 比如:我们开发了一个邮件发送程 ...

  2. JAVA - 守护线程(Daemon Thread)

    转载自:http://www.cnblogs.com/luochengor/archive/2011/08/11/2134818.html 在Java中有两类线程:用户线程 (User Thread) ...

  3. Java并发编程:线程控制

    在上一篇文章中(Java并发编程:线程的基本状态)我们介绍了线程状态的 5 种基本状态以及线程的声明周期.这篇文章将深入讲解Java如何对线程进行状态控制,比如:如何将一个线程从一个状态转到另一个状态 ...

  4. Java并发编程:线程池的使用

    Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...

  5. Java并发编程:线程间协作的两种方式:wait、notify、notifyAll和Condition

    Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition 在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者 ...

  6. Java并发编程:线程池的使用(转)

    Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...

  7. Java 并发编程:线程间的协作(wait/notify/sleep/yield/join)

    Java并发编程系列: Java 并发编程:核心理论 Java并发编程:Synchronized及其实现原理 Java并发编程:Synchronized底层优化(轻量级锁.偏向锁) Java 并发编程 ...

  8. Java并发编程:线程池的使用(转载)

    转载自:https://www.cnblogs.com/dolphin0520/p/3932921.html Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实 ...

  9. Java并发编程:线程池的使用(转载)

    文章出处:http://www.cnblogs.com/dolphin0520/p/3932921.html Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实 ...

随机推荐

  1. C语言基础四(敲打键盘、寻找资料,循环语句)请一个个字读,助于您的学会机率

    循环语句无非几种,常用的就有if()else()结构类型的,while(){}类型的,do(){}while(1);类型,switch()类型,for()类型. 而这章就将前面的所有知识全部汇总下运用 ...

  2. [OPENCV]cvHoughLines2使用说明

    1.cvHoughLines2函数定义: CvSeq *cvHoughLines2 { CvArr *image, void *line_storage, int method, double rho ...

  3. 3ds max学习笔记(三)--视点显示控制

    显示模式:1.模型一般是以实体方式显示的,若想看线框方式,摁F3:返回实体,摁F3:2.实体加线框模式显示,摁F4:返回,摁F4:3.透明效果:ALT+X,透明显示,之后F4,显示线框:程序内的其他显 ...

  4. 深入理解JVM(4)——对象内存的分配策略

    一.Java所承担的自动内存管理主要是针对对象内存的分配和回收. 二.在Java虚拟机的五块内存空间中,程序计数器.Java虚拟机栈.本地方法栈内存的分配和回收都具有确定性,一般在编译阶段就能确定需要 ...

  5. python正则表达式里引入变量

    import re def reg_exp(senten): jiqiren = "阿童木" matchObj1 = re.search( r'(你(.*?)(男|女))|(机器( ...

  6. js+css3+HTML5拖动滑块(type="range")改变值

    最近在做一个H5的改版项目,产品和设计给出的效果中有一个拖动滑块可以改变输入值的效果,类似如下图这样: 拿到这样的设计稿后,我有点懵了,自己写一个js?去网上找一个这样的效果?自己写一个可以,只是实现 ...

  7. javaScript系列 [02]-javaScript对象探析

    [02]-javaScript对象探析 题记:多年前,以非常偶然的方式关注了微信公众号“面向对象”,本以为这个公众号主要以分享面向对象编程的干货为主,不料其乃实实在在的猿圈相亲平台.通过查看公开资料, ...

  8. Ubuntu 18 LTS netplan 网络配置

    一.配置网络 1.通过netplan配置网络 #配置网络 nulige@ubuntu:/etc/netplan$ sudo apt install ifupdown nulige@ubuntu:/et ...

  9. Android、iOS、和Web如何做灰度发布?

        主要参考了: https://www.zhihu.com/question/21714205     https://www.zhihu.com/question/28296375  一.概述 ...

  10. [Vuex] Lazy Load a Vuex Module at Runtime using TypeScript

    Sometimes we need to create modules at runtime, for example depending on a condition. We could even ...