Java 的守护线程
Java 守护线程,看这篇文章就对了!
什么是Java的守护线程( Daemon Thread )?
Java 提供了两种类型的线程:守护线程 和 用户线程
- 用户线程 (User Thread) 是高优先级线程。JVM 会在终止之前等待任何用户线程完成其任务。
- 守护线程 (Daemon Thread) 是低优先级线程。其唯一作用是为用户线程提供服务。
举个例子:
任何一个守护线程都是整个JVM中所有非守护线程的保姆
只要当前JVM实例中尚存在任何一个非守护线程没有结束,守护线程就全部工作;只有当最后一个非守护线程结束时,守护线程随着JVM一同结束工作。
Daemon的作用是为其他线程的运行提供便利服务,守护线程最典型的应用就是 GC (垃圾回收器),它就是一个很称职的守护者。
守护线程的区别?
守护线程与普通线程唯一的区别是:
- 当线程退出时,JVM 会检查其他正在运行的线程,如果这些线程都是守护线程,那么 JVM 会正常退出操作。
- 但是如果有普通线程还在运行,JVM 是不会执行退出操作的。当 JVM 退出时,所有仍然存在的守护线程都将被抛弃,既不会执行 finally 部分的代码,也不会执行 stack unwound 操作,JVM 会直接退出。
When the JVM halts any remaining daemon threads are abandoned:
- finally blocks are not executed,
- stacks are not unwound - the JVM just exits.
守护线程的作用?
守护线程最常见的用法是用于:
- 后台支持任务:
- 垃圾回收
- 释放未使用对象的内存
- 从缓存中删除不需要的条目等。
这么看来,大多数 JVM 线程都是守护线程。
守护线程如何创建?
- 调用
Thread.setDaemon()
方法
守护线程也是一个线程,因此它的创建和启动其实和普通线程没什么区别?
要将普通线程设置为守护线程,方法很简单,只需要调用 Thread.setDaemon()
方法即可。
例如下面这段代码,假设我们继承 Thread
类创建了一个新类 NewThread
。那么我们就可以创建这个类的实例并设置为守护线程。
NewThread daemonThread = new NewThread();
daemonThread.setDaemon(true);
daemonThread.start();
守护线程如何判断?
- 调用
isDaemon()
方法
检查一个线程是否是守护线程,可以简单地调用方法 isDaemon()
,如下代码所示:
@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());
}
守护线程使用的注意事项
- 在
main()
方法内创建的任何线程默认为用户线程。
Java 语言中,线程的状态是自动继承的,故普通线程创建的子线程默认也是普通线程 setDaemon()
方法只能在创建Thread
对象并且在启动线程前调用
在线程运行时尝试调用setDaemon()
将抛出IllegalThreadStateException
异常。
总结
- 守护线程是Java两种线程的一种,又被称为“保姆线程”。
- 守护线程常用于后台支持任务,例如垃圾回收、释放未使用对象的内存等。
- 调用
Thread.setDaemon()
方法将用户线程设置为守护线程。 - 在 Java 语言中,线程的状态是自动继承的。用户线程的子线程默认为用户线程,守护线程的子线程默认为守护线程。
- 守护线程只能在用户线程之前启动,否则报
IllegalThreadStateException
异常。