记录一个小知识点,用户线程和 守护线程。
相信有很多小伙伴不清楚这两个线程都是干嘛用的吧?希望通过这篇文章的简短描述能让你有所收货。
用户线程
平时在项目开发中,使用的线程一般都是用户线程。【四种创建线程的方式】
守护线程
守护线程和用户线程的创建方式一样,有一点需要注意的是,它需要在启动线程前,设置为守护线程,即:thread.setDaemon(true); 然后再启动。
守护线程不会影响 JVM 进程的正常退出。
守护线程代码演示
首先来看一下用户线程:
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
boolean daemon = Thread.currentThread().isDaemon();
System.out.println(Thread.currentThread().getName() + " 是守护线程还是用户线程?" + (daemon ? "守护线程" : "用户线程"));
while (!Thread.currentThread().isInterrupted()) {
}
},"t1");
t1.start();
System.out.println("main 线程【用户线程】执行结束!!!");
}
执行结果:
可以发现,默认 new 出来的线程,都是用户线程。当主线程执行结束后,另外一个用户线程并没有一起跟着结束。下来,将代码稍微改动一下,将 t1 置为守护线程,为主线程服务,当主线程销毁后,守护线程自动结束。
public static void main(String[] args) throws InterruptedException {
Runtime.getRuntime().addShutdownHook(new Thread(() -> System.out.println("JVM 进程结束!!")));
Thread t1 = new Thread(() -> {
boolean daemon = Thread.currentThread().isDaemon();
System.out.println(Thread.currentThread().getName() + " 是守护线程还是用户线程?" + (daemon ? "守护线程" : "用户线程"));
while (!Thread.currentThread().isInterrupted()) {
}
},"t1");
// 将 t1 线程设置为守护线程,主线程销毁后,自动终止
t1.setDaemon(true);
t1.start();
Thread.sleep(3000);
System.out.println("main 线程【用户线程】执行结束!!!");
}
执行结果:
Runtime.getRuntime().addShutdownHook();
这一行代码,可以用来注册 JVM关闭的钩子,在程序正常退出、系统关闭、OOM 宕机时被回调。
守护线程存在的意义
通过以上代码演示,相信小伙伴们一定清楚了什么是用户线程、什么是守护线程,那么守护线程存在的意义又是什么?在哪些场景中会用到守护线程呢?
- 比如在 JVM 中的垃圾回收器就采用了守护线程,如果一个程序中没有任何用户线程,那么就不会产生辣鸡,垃圾回收器也就不需要工作了。
- 在一些中间件的心跳检测、事件监听等涉及定时异步执行的场景中也可以使用守护线程,因为这些都是在后台不断执行的任务,当进程退出时,这些任务也不需要存在,而守护线程也可以自动结束自己的生命周期。
从这些实际应用场景中可以看出,对于一些后台任务,当不希望阻止 JVM 进程结束时,可以采用守护线程。