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我们可以确认到:
-
主线程结束后,守护线程也会随着结束
-
守护线程结束后,finally 中的语句也不会被执行
通过源代码我们可以分析到:
因为 isAlive() 函数的存在,我们不能将已激活的线程定义为守护线程