java并发系列-Java中的守护线程

1 简介

这篇文章讨论守护进程有什么用途,以及它们跟用户线程的区别。

2 守护线程和用户线程的区别

Java提供两类线程:用户线程(user thread)和守护线程(daemon thread)。

用户线程是高优先级线程。JVM在终止用户线程之前,会等待它们完成任务。

相反,守护线程是低优先级线程,它唯一角色就是为用户线程提供服务。

因为守护线程是服务用户线程的并且只用在用户线程执行的时候,所以当所有用户线程结束执行时,守护线程不会阻止JVM退出。

这就是为什么守护进程存在无限循环也不会有问题的原因。因为一旦所有用户线程结束执行,任何代码包括finally块都不会执行。也因此,对于I/O任务,不推荐使用守护线程。

不过,也有一些情况不遵循这个规则。比如,在运行的守护线程上调用Thread.join()就可以阻塞程序退出。

3 守护线程的用法

守护线程对后台辅助任务很有用,比如垃圾收集(gc),释放无用对象的内存和从缓存删除不需要的条目、大多数的JVM线程是守护线程。

4 创建一个守护线程

将线程设置为守护线程,只需要调用Thread.setDaemon()。例如,下面继承了ThreadNewThread类:

1
2
3
NewThread daemonThread = new NewThread();
daemonThread.setDaemon(true);
daemonThread.start();

任何线程设置了守护状态即创建了守护线程。因为main线程是用户线程,所以任何在main方法中创建的线程默认都是用户线程。

setDaemon()方法只能在Thread对象被创建后还没有调用start()前调用。尝试对运行中的线程调用setDaemon()方法会抛出IllegalThreadStateException

1
2
3
4
5
6
@Test(expected = IllegalThreadStateException.class)
public void whenSetDaemonWhileRunning_thenIllegalThreadStateException() {
NewThread daemonThread = new NewThread();
daemonThread.start();
daemonThread.setDaemon(true);
}

5 校验线程是不是守护线程

最后,验证一个线程是不是守护线程,只需调用 isDaemon() 就可以。

1
2
3
4
5
6
7
8
9
10
11
@Test
public void whenCallIsDaemon_thenCorrect() {
NewThread daemonThread = new NewThread();
NewThread userThread = new NewThread();
daemonThread.setDaemon(true);
daemonThread.start();
userThread.start();

assertTrue(daemonThread.isDaemon());
assertFalse(userThread.isDaemon());
}

6 总结

这篇文章,介绍了守护线程是什么,用在什么场景中。


本文为译文,作者通过翻译达到学习目的。 原文链接 | 原文源码链接 | 本站源码链接