JUC源码解读:守护线程——分析setDaemon()

Java高并发讲解:守护线程——在源代码中分析setDaemon()

提出问题

我们都知道Java线程分为主线程和守护线程,守护线程是需要手动指定的(setDaemon(true)😉,并且主线程一结束守护线程就不存在了,我写一段demo,大家可以看一看

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

        Thread daemon = new Thread(new DaemonThread(), "daemonThread");
        daemon.setDaemon(true); // 定义为守护线程
        daemon.start();
    }

    static class DaemonThread implements Runnable {

        @Override
        public void run() {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } finally {
                System.out.println("守护线程执行了: " + Thread.currentThread().getName());
            }
        }
    }

输出结果是空

因此,即使把输出语句写在 finally 块中,语句也不会被执行

接下来,我们进入 setDaemon() 源码中,看一看守护线程是怎么被定义的吧

源码分析

    public final void setDaemon(boolean on) {
        checkAccess(); // 检查线程
        if (isAlive()) {
            throw new IllegalThreadStateException();
        }
        daemon = on; // 标记为守护线程
    }

isAlive() 函数是关键,如果为 false 会抛出“线程状态异常”

isAlive 函数是个什么东西?我们看一下它的源码

public final native boolean isAlive();

这是一个OS级别的函数,目的是检查线程是否已经被激活了,(也就是是否已经 Thread.start() 了)

如果 isAlive() 为 true,就不能被定义为守护线程,而是“抛出线程状态异常了”

总结

通过demo我们可以确认到:

  1. 主线程结束后,守护线程也会随着结束

  2. 守护线程结束后,finally 中的语句也不会被执行

通过源代码我们可以分析到:

​因为 isAlive() 函数的存在,我们不能将已激活的线程定义为守护线程

posted @ 2024-03-11 19:00  yangruomao  阅读(13)  评论(0编辑  收藏  举报