前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >Java用户线程和守护线程,线程默认Daemon值是false吗?

Java用户线程和守护线程,线程默认Daemon值是false吗?

作者头像
鱼找水需要时间
发布2023-02-16 20:14:18
发布2023-02-16 20:14:18
78600
代码可运行
举报
文章被收录于专栏:SpringBoot教程SpringBoot教程
运行总次数:0
代码可运行

文章目录

Java中通常有两种线程: 用户线程守护线程(也被称为服务线程) 通过 Thread.setDaemon(false)设置为 用户线程(默认为用户线程) 通过 Thread.setDaemon(true)设置为 守护线程 线程属性的设置要在线程启动 之前,否则会报 IllegalThreadStateException异常

用户线程

代码语言:javascript
代码运行次数:0
复制
public static void main(String[] args) {
    Thread thread = new Thread(()->{
        System.out.println("开始执行:" + Thread.currentThread().getName());
        while (true){

        }
    }, "t1");
    thread.start();
    System.out.println("主线程结束");
}

运行结果如下:

可以看到主线程已经结束,但程序确无法退出。因为t1线程是用户线程,里边是一个死循环使线程一直处于运行状态,所以无法结束

守护线程

代码语言:javascript
代码运行次数:0
复制
public static void main(String[] args) {
    Thread thread = new Thread(()->{
        System.out.println("开始执行:" + Thread.currentThread().getName());
        while (true){

        }
    }, "t1");
    thread.setDaemon(true);
    thread.start();
    System.out.println("主线程结束");
}

运行结果如下:

通过thread.setDaemon(true)设置t1线程为守护线程,程序随着主线程的结束而结束

结论:当程序中所有的用户线程执行完毕之后,不管守护线程是否结束,系统都会自动退出。

必须要在start()方法之前设置守护线程

源码里也有声明,必须在线程启动之前调用setDaemon方法。

守护线程是一种特殊的线程,在后台默默地完成一些系统性的服务,比如垃圾回收线程JIT线程都是守护线程。与之对应的是用户线程用户线程可以理解为是系统的工作线程,它会完成这个程序需要完成的业务操作。如果用户线程全部结束了,意味着程序需要完成的业务操作已经结束了,系统可以退出了。所以当系统只剩下守护进程的时候,Java虚拟机会自动退出

线程默认的daemon值

首先看一下创建线程源码,Thread类的init()方法

也就是说线程的daemon的默认值取决于父线程的daemon值,当父线程为用户线程,子线程默认是用户线程,当父线程为守护线程时 子线程也为守护线程。

示例代码

代码语言:javascript
代码运行次数:0
复制
public static void main(String[] args) throws InterruptedException {
    Thread thread = new Thread(()->{
        System.out.println("t1 isDaemon:" + Thread.currentThread().isDaemon());
    }, "t1");
    thread.start();
    System.out.println("主线程 isDaemon:" + Thread.currentThread().isDaemon());

    TimeUnit.SECONDS.sleep(2);
}

运行结果:

t1线程是由main方法所在的线程创建的,主线程是t1的父线程,主线程为用户线程,所以t1.isDaemonfalse,两个都为用户线程


示例代码2

代码语言:javascript
代码运行次数:0
复制
public static void main(String[] args) throws InterruptedException {
    Thread thread = new Thread(()->{
        System.out.println("t1 isDaemon:" + Thread.currentThread().isDaemon());
        new Thread(()->{
            System.out.println("t2 isDaemon:" + Thread.currentThread().isDaemon());
        }, "t2").start();
    }, "t1");
    thread.setDaemon(true);
    thread.start();
    System.out.println("主线程 isDaemon:" + Thread.currentThread().isDaemon());

    TimeUnit.SECONDS.sleep(2);
}

运行结果:

t1线程手动设置了为守护线程,t1线程为t2线程的父线程,线程是否为守护线程默认取决于父线程的值,也就是说t2默认线程类型和t1一样的,都为守护线程。

总结

  1. java中的线程分为用户线程守护线程(ps:还有虚拟线程也叫协程)
  2. 程序中的所有的用户线程结束之后,不管守护线程处于什么状态,java虚拟机都会自动退出
  3. 调用线程的实例方法setDaemon()来设置线程是否是守护线程
  4. setDaemon()方法必须在线程的start()方法之前调用,在后面调用会报异常,并且不起效
  5. 线程的daemon默认值和其父线程一样。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-12-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 用户线程
  • 守护线程
  • 必须要在start()方法之前设置守护线程
  • 线程默认的daemon值
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档