1、什么是守护线程
Java线程分两种:用户线程和守护线程。
守护线程,是指在程序运行的时,后台提供一种通用服务的线程。比如垃圾回收线程就是一个很称职的守护者,并且这种线程并不属于程序中不可或缺的部分。因此,当所有的非守护线程结束时,程序也就终止了,同时会杀死进程中的所有守护线程。反过来说,只要任何非守护线程还在运行,程序就不会终止。
守护线程和用户线程的没有本质的区别,不同之处在于虚拟机的离开;若用户线程已全部退出运行,只剩守护线程存在,虚拟机也即退出。 因没有了被守护者,守护线程也就无工作可做,也就没有继续运行程序的必要了。
将线程转换为守护线程可以通过调用Thread对象的setDaemon(true)方法来实现。在使用守护线程时需要注意一下几点:
(1)thread.setDaemon(true)须在thread.start()之前设置,不能把正在运行的常规线程设置为守护线程,否则会抛出IllegalThreadStateException异常。
(2) 在Daemon线程中创建的新线程也是Daemon的。
(3) 守护线程应该永远不去访问固有资源,如文件、数据库,因为它会在任何时候甚至在一个操作的中间发生中断。
(4)java多线程编程,偏向使用java自带的多线程框架,比如ExecutorService,但是java的线程池会将守护线程转换为用户线程,所以如果要使用后台线程就不能用java的线程池。
2、代码示例
守护线程类
import lombok.SneakyThrows;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DaemonRunnable implements Runnable {
@SneakyThrows
@Override
public void run() {
System.out.println("进入守护线程...");
Integer count = 0;
while (true) {
count++;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = sdf.format(new Date());
System.out.println("当前:" + time + " | 守护线程进行中,目前计数至【" + count + "】");
Thread.sleep(1000);
}
}
}
测试类
import java.util.Random;
public class DaemonTest {
public static void main(String[] args) throws InterruptedException {
// 守护线程在主线程操作完成后就会自动退出,所以不适合进行读写操作
DaemonRunnable runnable = new DaemonRunnable();
Thread thread = new Thread(runnable);
thread.setDaemon(true);
thread.start();
Random random = new Random();
Integer sec = random.nextInt(10);
System.out.println("警告:" + sec + "秒后主线程退出");
Thread.sleep(sec * 1000);
System.out.println("警告:主线程宣告退出!");
}
}
测试结果
进入守护线程...
警告:8秒后主线程退出
当前:2021-10-09 15:40:00 | 守护线程进行中,目前计数至【1】
当前:2021-10-09 15:40:01 | 守护线程进行中,目前计数至【2】
当前:2021-10-09 15:40:02 | 守护线程进行中,目前计数至【3】
当前:2021-10-09 15:40:03 | 守护线程进行中,目前计数至【4】
当前:2021-10-09 15:40:04 | 守护线程进行中,目前计数至【5】
当前:2021-10-09 15:40:05 | 守护线程进行中,目前计数至【6】
当前:2021-10-09 15:40:06 | 守护线程进行中,目前计数至【7】
当前:2021-10-09 15:40:07 | 守护线程进行中,目前计数至【8】
警告:主线程宣告退出!