首页 > 编程语言 >Java守护线程

Java守护线程

时间:2022-11-04 11:45:35浏览次数:42  
标签:daemon Java Thread setDaemon 线程 println 守护

Java中,通过Thread类,我们可以创建2种线程,分为守护线程和用户线程。

守护线程是所有非守护线程的保姆,当所有非守护线程执行完成或退出了,即使还有守护线程在运行,JVM也会直接退出,因此守护线程通常是用来处理一些辅助工作。

反之,对于非守护线程,只要有一个在运行,JVM就不会退出。

典型的守护线程如垃圾回收GC线程,当用户线程都结束后,GC也就没有单独存在的必要,JVM直接退出。

 

我们可以通过Thread对象的setDaemon(boolean on)方法设置是否为守护线程,要在start之前设置:

Thread thread = new Thread(runnable);
thread.setDaemon(true); // true表示守护线程,false表示用户线程
thread.start();

 

需要注意的是,如果没有显示调用setDaemon方法进行设置,线程的模式是取决于父线程是否为守护线程,也就是创建此线程所在的线程。

如果父线程是守护线程,创建的线程默认是守护线程;

如果父线程是用户线程,创建的线程默认是用户线程。

 

这可以从Thread类的init方法源代码中看出:

Thread parent = currentThread();
this.daemon = parent.isDaemon();

 

对于daemon的设置,保存在了Thread对象的成员变量中,Thread提供了setter/getter:

private boolean daemon = false;		//	是否为守护线程

public final void setDaemon(boolean on) {
    //	SecurityManager安全检查,本文不展开讨论
    checkAccess();
	//	检查线程是否已启动,已启动无法设置daemon
    if (isAlive()) {
        throw new IllegalThreadStateException();
    }
    daemon = on;
}

public final boolean isDaemon() {
    return daemon;
}

 

setDaemon方法中通过isAlive判断线程是否已启动,已启动状态下不允许修改,抛出IllegalThreadStateException异常。

 

接着我们用示例来验证一下守护线程和非守护线程的区别。

 

以下是守护线程示例:

Thread t = new Thread(() -> {
    System.out.println("before");
    ThreadUtil.sleep(5000);
    System.out.println("after");
});
//	显式设置daemon为true
t.setDaemon(true);
t.start();

ThreadUtil.sleep(1000);
System.out.println("exit");

输出:

before
exit

可以发现,当线程设置为守护线程后,主线程一旦执行完毕,程序退出,守护线程也随着立即终止。

 

以下是非守护线程示例:

Thread t = new Thread(() -> {
    System.out.println("before");
    ThreadUtil.sleep(5000);
    System.out.println("after");
});
//	显式设置daemon为false
t.setDaemon(false);
t.start();

ThreadUtil.sleep(1000);
System.out.println("exit");

输出:

before
exit
after

虽然主线程已经执行完毕,但创建的非守护线程还在运行。

 

具体JVM是如何通过daemon字段控制线程的,这在JDK中找不到相应源码,需要深入hotspot C++源码进行分析,后续有必要再追加更新。

标签:daemon,Java,Thread,setDaemon,线程,println,守护
From: https://www.cnblogs.com/ladderx/p/16857211.html

相关文章

  • 案例2:JAVA GUI 简易计算器
    使用javaGUI实现计算器的基本功能,包含一个帮助说明页面,提示用户如何使用。包含一个计算器主界面,要实现基本的加法、减法、乘法、除法运算。1.帮助界面   Help.java......
  • Rocksdb 的优秀代码(三)-- 工业级 线程池实现分享
    文章目录​​前言​​​​1.Rocksdb线程池概览​​​​2.Rocksdb线程池实现​​​​2.1基本数据结构​​​​2.2线程池创建​​​​2.3线程池调度线程执行​​​​2.......
  • 案例3:JAVA GUI 随机点名程序
    先开发一个姓名维护的界面,输入学生的姓名,每行录入一个学生姓名,点击保存的时候将学生的姓名保存到一个txt文件中。再开发一个点名的程序,从维护好的txt文件中,随机读取一个学......
  • 关于 线程模型中经常使用的 __sync_fetch_and_add 原子操作的性能
    最近从kvell这篇论文中看到一些单机存储引擎的优秀设计,底层存储硬件性能在不远的未来可能不再是主要的性能瓶颈,反而高并发下的CPU可能是软件性能的主要限制。像BPS/AEP/Op......
  • JavaIo案例
    FIleFIle是文件对象,可以表示一个文件,也可以表示文件夹。研究其源码,没有什么意义,我们要做的,是研究怎么用。常用的文件操作方式一:根据路径创建一个文件(只能创建在磁盘根......
  • Java学习——11.04
    因为昨天学的有点少,上不了台面,所以和今天的一起写,当然还可能是自己太懒了,昨天的没记住,于是又看了一遍。1.变量:局部变量(和C一样的)实例变量(加new引用文件名创建函数......
  • 十堰网站建设用php、java、.net哪个编程语言好
    前言对于这个问题,我的回答是:在十堰网站建设时没有什么编程语言是最好的,只有适合自己的才是最好的!或许你对我的回复不是很满意,不过没关系,你可以看看我的分析就知道了。Php......
  • 死磕面试系列,Java到底是值传递还是引用传递?
    Java到底是值传递还是引用传递?这虽然是一个老生常谈的问题,但是对于没有深入研究过这块,或者Java基础不牢的同学,还是很难回答得让人满意。可能很多同学能够很轻松的背出JVM......
  • Java核心工具库Guava介绍以及Optional和Preconditions使用进行非空和数据校验
    场景GuavaGuava项目是Google公司开源的Java核心库,它主要是包含一些在Java开发中经常使用到的功能,如数据校验、不可变集合、计数集合,集合增强操作、I/O、缓存、字......
  • JavaScript异或运算
    相关性质任何数和自己做异或运算,结果为0,即a⊕a=0a⊕a=0。任何数和0做异或运算,结果还是自己,即a⊕0=⊕a⊕0=⊕。异或运算中,满足交换律和结合律,也就是a⊕b⊕a=b⊕a⊕......