目录
为什么存在
什么是守护线程
创建守护线程
在使用守护线程时需要注意以下几点
可以使用isDaemon()方法来检查线程是否是守护线程
例1:上面提到当JVM中只剩下守护线程的时候,JVM就会退出,那么写段代码测试下
例2:thread是用户线程,主线程结束后,thread会继续运行
例3:thread是守护线程,主线程结束后,thread会随即停止
为什么存在
- Java程序入口就是由JVM启动main线程,main线程又可以启动其他线程
- 当所有线程都运行结束时,JVM退出,进程结束
- 如果有一个线程没有退出,JVM进程就不会退出
- 所以,必须保证所有线程都能及时结束
- 但是有一种线程的目的就是无限循环
- 例如,一个定时触发任务的线程:
- 如果这个线程不结束,JVM进程就无法结束
- 问题是,由谁负责结束这个线程?
- 然而这类线程经常没有负责人来负责结束它们
- 但是,当其他线程结束时,JVM进程又必须要结束,怎么办?
- 答案是使用守护线程(Daemon Thread)
- 守护线程是指为其他线程服务的线程
- 在JVM中,所有非守护线程都执行完毕后,无论有没有守护线程,虚拟机都会自动退出
- 因此,JVM退出时,不必关心守护线程是否已结束
什么是守护线程
- 在Java中有两类线程:User Thread(用户线程)、Daemon Thread(守护线程)
- 它们通过Thread的daemon属性标识:true表示守护线程,false表示用户线程
- 用户线程一般用于执行用户级任务
- 而守护线程也就是“后台线程”,一般用来执行后台任务
- 并且这种线程并不属于程序中不可或缺的部分
- 因此,当所有的非守护线程结束时,程序也就终止了
- 同时会杀死进程中的所有守护线程
- 反过来说,只要任何非守护线程还在运行,程序就不会终止
- 守护线程最典型的应用就是GC(垃圾回收器)
- 这两种线程其实是没有什么区别的
- 唯一的区别就是Java虚拟机在所有<用户线程>都结束后就会退出,而不会等<守护线程>执行完
- 当所有的非守护线程结束时,程序也就终止了
- 因为没有了被守护者,守护线程也就没有工作可做了,也就没有继续运行程序的必要了
- GC线程就是一个守护线程,保持低优先级进行垃圾回收,不依赖系统资源
- 当所有用户线程退出之后,GC线程也就没有什么用了,会随即退出
- 因为如果没有用户线程了,也就代表没有垃圾会继续产生,也就不需要GC线程了
- 可以简单理解成守护线程为用户线程服务,当所有用户线程结束,也就不需要守护线程了
创建守护线程
- 将线程转换为守护线程可以通过调用Thread对象的setDaemon(true)方法来实现,使线程成为一个守护线程
在使用守护线程时需要注意以下几点
- 1-thread.setDaemon(true)必须在thread.start()之前设置,否则会抛出一个IllegalThreadStateException异常
- 你不能把正在运行的常规线程设置为守护线程
- 2-在Daemon线程中产生的新线程也是Daemon的
- 3-守护线程应该永远不去访问固有资源,如文件、数据库,因为它会在任何时候甚至在一个操作的中间发生中断,这会导致数据丢失
可以使用isDaemon()方法来检查线程是否是守护线程
- 以上代码输出结果:
例1:上面提到当JVM中只剩下守护线程的时候,JVM就会退出,那么写段代码测试下
- 以上代码中,我们在Main线程中开启了一个子线程
- 在并没有显示将其设置为守护线程的情况下,他是一个用户线程
- 代码比较好理解,就是子线程处于一个while(true)循环中,每隔一秒打印一次I'm child thread..
- 输出结果为:
- 我们再把子线程设置成守护线程,重新运行以上代码:
- 以上代码,我们通过childThread.setDaemon(true);把子线程设置成守护线程,然后运行,得到以下结果:
- 子线程只打印了一次
- 也就是在main线程执行结束后,由于子线程是一个守护线程,JVM就会直接退出了
- 值得注意的是,在Daemon线程中产生的新线程也是Daemon的