并发基础7(守护线程)
目录
1:什么守护线程
2:守护线程使用
3:守护线程案例
1:什么守护线程
守护线程是Java中的一种特殊的线程类型,它为其他线程(非守护线程)提供后台支持服务。
在Java多线程编程中,有两种特殊类型的线程:后台线程和守护线程。这两种线程在一些特定的场景下非常有用,但也需要谨慎使用。本文将详细介绍后台线程和守护线程的概念、特性、用法,以及注意事项。
守护线程的特点
服务性质:守护线程通常用于执行后台任务,如JVM的垃圾回收、内存管理等
生命周期依赖:当所有非守护线程结束时,JVM会自动退出,不管是否还有守护线程在运行
优先级低:守护线程的优先级比较低
后台线程和守护线程的生命周期都取决于是否还有前台线程在运行。如果所有前台线程都结束了,那么后台线程和守护线程会自动退出。
守护线程 vs 非守护线程
特性 | 守护线程 | 非守护线程(用户线程) |
---|---|---|
JVM退出影响 | 不阻止JVM退出 | 会阻止JVM退出 |
默认类型 | 否 | 是(默认) |
典型用途 | 后台服务 | 程序主逻辑 |
子线程继承 | 继承父线程的守护状态 | 继承父线程的守护状态 |
2:守护线程使用
Thread backgroundThread = new Thread(() -> {// 后台线程的工作
});
//在启动前设置setDaemon是true
backgroundThread.setDaemon(true);
backgroundThread.start();
3:守护线程案例
场景一:定时任务
后台线程和守护线程非常适合执行定时任务。你可以创建一个后台线程或守护线程来执行周期性的任务,例如定时清理临时文件、定时发送心跳包等。
Thread timerThread = new Thread(() -> {while (true) {// 执行定时任务try {Thread.sleep(1000); // 暂停1秒钟} catch (InterruptedException e) {e.printStackTrace();}}
});
timerThread.setDaemon(true); // 设置为守护线程
timerThread.start();
场景二:垃圾回收
垃圾回收器是Java中的经典守护线程的例子。垃圾回收线程会自动回收不再使用的内存,无需程序员的干预。这是Java内存管理的重要组成部分。
public class GarbageCollectorExample {public static void main(String[] args) {// 创建一个后台线程来执行垃圾回收Thread garbageCollectorThread = new Thread(() -> {while (true) {System.gc(); // 手动触发垃圾回收try {Thread.sleep(60000); // 每分钟执行一次垃圾回收} catch (InterruptedException e) {e.printStackTrace();}}});garbageCollectorThread.setDaemon(true); // 设置为守护线程garbageCollectorThread.start();// 模拟应用程序的主要工作for (int i = 0; i < 10; i++) {System.out.println("Main Thread is running...");try {Thread.sleep(2000); // 主线程每2秒输出一次} catch (InterruptedException e) {e.printStackTrace();}}}
}
在上面的示例中,我们创建了一个后台线程 garbageCollectorThread
,它会每分钟执行一次垃圾回收。主线程会模拟应用程序的主要工作。由于 garbageCollectorThread
是后台线程,当主线程结束时,它会自动退出。
场景三:日志记录
在某些情况下,你可能希望在后台记录日志,而不干扰主要的应用程序流程。后台线程可以用于将日志信息写入文件或发送到远程日志服务器。
public class LoggingExample {public static void main(String[] args) {// 创建一个后台线程来执行日志记录Thread loggingThread = new Thread(() -> {while (true) {logMessage("This is a log message.");try {Thread.sleep(5000); // 每5秒记录一条日志} catch (InterruptedException e) {e.printStackTrace();}}});loggingThread.setDaemon(true); // 设置为守护线程loggingThread.start();// 模拟应用程序的主要工作for (int i = 0; i < 10; i++) {System.out.println("Main Thread is running...");try {Thread.sleep(2000); // 主线程每2秒输出一次} catch (InterruptedException e) {e.printStackTrace();}}}private static void logMessage(String message) {// 此处可以将日志信息写入文件或发送到远程日志服务器System.out.println("Logging: " + message);}
}
在上面的示例中,我们创建了一个后台线程 loggingThread
,它会每5秒记录一条日志。主线程模拟应用程序的主要工作。 logMessage
方法用于记录日志信息,你可以根据实际需求将日志信息写入文件或发送到远程日志服务器。由于 loggingThread
是后台线程,当主线程结束时,它会自动退出。
这些示例演示了如何使用后台线程执行垃圾回收和日志记录任务,同时确保这些线程不会阻止应用程序的正常退出。