014-十四、Java并发 Java 守护线程 ( Daemon Thread )
引言
在这篇简短的文章中,我们将讲解下 Java
中的守护线程,看看它们可以做什么。我们还将解释守护线程和用户线程之间的区别。
守护线程和用户线程的区别
Java 提供了两种类型的线程:守护线程 和 用户线程
- 用户线程 是高优先级线程。
JVM
会在终止之前等待任何用户线程完成其任务。 - 用户线程 是低优先级线程。其唯一作用是为用户线程提供服务。
由于守护线程的作用是为用户线程提供服务,并且仅在用户线程运行时才需要,因此一旦所有用户线程完成执行,JVM
就会终止。也就是说 守护线程不会阻止 JVM 退出。
这也是为什么通常存在于守护线程中的无限循环不会导致问题,因为任何代码(包括 finally
块 )都不会在所有用户线程完成执行后执行。
这也是为什么我们并不推荐 在守护线程中执行 I/O 任务 。因为可能导致无法正确关闭资源。
但是,守护线程并不是 100%
不能阻止 JVM
退出的。守护线程中设计不良的代码可能会阻止 JVM 退出。例如,在正在运行的守护线程上调用Thread.join()
可以阻止应用程序的关闭。
守护线程能用来做什么?
常见的做法,就是将守护线程用于后台支持任务,比如垃圾回收、释放未使用对象的内存、从缓存中删除不需要的条目。
咦,按照这个解释,那么大多数 JVM 线程都是守护线程。
如何创建守护线程 ?
守护线程也是一个线程,因此它的创建和启动其实和普通线程没什么区别?
要将普通线程设置为守护线程,方法很简单,只需要调用 Thread.setDaemon()
方法即可。
例如下面这段代码,假设我们继承 Thread
类创建了一个新类 NewThread
。那么我们就可以创建这个类的实例并设置为守护线程
NewThread daemonThread = new NewThread();
daemonThread.setDaemon(true);
daemonThread.start();
在 Java 语言中,线程的状态是自动继承的。任何线程都会继承创建它的线程的守护程序状态。怎么理解呢?
1、 如果一个线程是普通线程( 用户线程) ,那么它创建的子线程默认也是普通线程( 用户线程 )。
2、 如果一个线程是守护线程,那么它创建的子线程默认也是守护线程。
因此,我们可以推演出: 由于主线程是用户线程,因此在 main()
方法内创建的任何线程默认为用户线程。
需要注意的是调用 setDaemon()
方法的时机,该方法只能在创建 Thread
对象并且在启动线程前调用。在线程运行时尝试调用 setDaemon()
将抛出 IllegalThreadStateException
异常。
@Test(expected = IllegalThreadStateException.class)
public void whenSetDaemonWhileRunning_thenIllegalThreadStateException() {
NewThread daemonThread = new NewThread();
daemonThread.start();
daemonThread.setDaemon(true);
}
如何检查一个线程是守护线程还是用户线程?
检查一个线程是否是守护线程,可以简单地调用方法 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());
}
后记
守护线程的概念是不是很简单?
写完了如果写得有什么问题,希望读者能够给小编留言,也可以点击[此处扫下面二维码关注微信公众号](https://www.ycbbs.vip/?p=28 "此处扫下面二维码关注微信公众号")
看完两件小事
如果你觉得这篇文章对你挺有启发,我想请你帮我两个小忙:
- 把这篇文章分享给你的朋友 / 交流群,让更多的人看到,一起进步,一起成长!
- 关注公众号 「方志朋」,公众号后台回复「666」 免费领取我精心整理的进阶资源教程
本文著作权归作者所有,如若转载,请注明出处
转载请注明:文章转载自「 Java极客技术学习 」https://www.javajike.com