本文目录导读:

我来详细介绍Java守护线程的创建方法和案例:
什么是守护线程
- 守护线程(Daemon Thread):在后台运行,为其他线程提供服务
- 用户线程:执行主要的业务逻辑
- 特点:当所有用户线程结束,JVM会自动退出,不等待守护线程完成
创建守护线程的基本方法
使用setDaemon(true)
public class DaemonThreadExample1 {
public static void main(String[] args) {
Thread daemonThread = new Thread(() -> {
while (true) {
try {
System.out.println("守护线程运行中...");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
// 设置为守护线程(必须在start之前)
daemonThread.setDaemon(true);
daemonThread.start();
System.out.println("主线程结束");
// 主线程结束后,JVM不会等待守护线程,直接退出
}
}
通过ThreadFactory创建
import java.util.concurrent.ThreadFactory;
public class DaemonThreadExample2 {
public static void main(String[] args) {
ThreadFactory daemonFactory = r -> {
Thread t = new Thread(r);
t.setDaemon(true);
t.setName("守护线程-" + System.currentTimeMillis());
return t;
};
Runnable task = () -> {
while (true) {
System.out.println(Thread.currentThread().getName() + " 运行中");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread daemonThread = daemonFactory.newThread(task);
daemonThread.start();
}
}
实际应用案例
案例1:后台日志记录器
import java.io.FileWriter;
import java.io.IOException;
import java.time.LocalDateTime;
public class LogDaemonDemo {
private static class LogWorker implements Runnable {
private volatile boolean running = true;
@Override
public void run() {
try (FileWriter writer = new FileWriter("app.log", true)) {
while (running) {
String log = LocalDateTime.now() + " - 系统运行正常\n";
writer.write(log);
writer.flush();
System.out.print(".");
Thread.sleep(2000);
}
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
public void stop() {
this.running = false;
}
}
public static void main(String[] args) throws InterruptedException {
LogWorker logWorker = new LogWorker();
Thread logThread = new Thread(logWorker);
logThread.setDaemon(true);
logThread.start();
// 模拟主程序运行
System.out.println("主程序开始运行");
Thread.sleep(5000);
System.out.println("\n主程序结束");
// JVM自动退出,守护线程终止
}
}
案例2:监控和清理服务
public class MonitorDaemonDemo {
// 模拟心跳监控
static class HeartbeatMonitor implements Runnable {
@Override
public void run() {
int count = 0;
while (true) {
try {
System.out.println("[监控] 系统心跳检查 #" + (++count));
// 模拟检查系统资源
Runtime runtime = Runtime.getRuntime();
long usedMemory = (runtime.totalMemory() - runtime.freeMemory()) / 1024 / 1024;
System.out.println("[监控] 当前内存使用: " + usedMemory + "MB");
Thread.sleep(3000);
} catch (InterruptedException e) {
System.out.println("[监控] 监控服务中断");
break;
}
}
}
}
// 模拟缓存清理
static class CacheCleaner implements Runnable {
@Override
public void run() {
while (true) {
try {
System.out.println("[清理] 开始清理临时缓存...");
// 模拟清理操作
Thread.sleep(5000);
System.out.println("[清理] 缓存清理完成");
} catch (InterruptedException e) {
System.out.println("[清理] 清理服务中断");
break;
}
}
}
}
public static void main(String[] args) throws InterruptedException {
// 创建监控守护线程
Thread monitorThread = new Thread(new HeartbeatMonitor());
monitorThread.setDaemon(true);
monitorThread.setName("监控线程");
// 创建清理守护线程
Thread cleanerThread = new Thread(new CacheCleaner());
cleanerThread.setDaemon(true);
cleanerThread.setName("清理线程");
monitorThread.start();
cleanerThread.start();
// 主业务逻辑
System.out.println("系统启动完成");
for (int i = 1; i <= 5; i++) {
System.out.println("处理业务请求 #" + i);
Thread.sleep(1500);
}
System.out.println("所有业务处理完成,系统即将关闭...");
// 主线程结束后,守护线程自动终止
}
}
案例3:超时监控器
public class TimeoutDaemonDemo {
// 模拟一个需要超时监控的任务
static class TimeoutMonitor implements Runnable {
private final long timeout;
private volatile boolean taskCompleted = false;
public TimeoutMonitor(long timeout) {
this.timeout = timeout;
}
@Override
public void run() {
long startTime = System.currentTimeMillis();
while (!taskCompleted) {
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed > timeout) {
System.out.println("[超时监控] 任务执行超时!已执行: " + elapsed + "ms");
// 可以在这里执行超时处理逻辑
taskCompleted = true;
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
System.out.println("[超时监控] 监控被中断");
break;
}
}
}
public void markCompleted() {
this.taskCompleted = true;
}
}
public static void main(String[] args) throws InterruptedException {
TimeoutMonitor monitor = new TimeoutMonitor(3000); // 3秒超时
Thread monitorThread = new Thread(monitor);
monitorThread.setDaemon(true);
monitorThread.start();
// 模拟一个长时间运行的任务
System.out.println("开始执行耗时任务...");
Thread.sleep(5000); // 模拟5秒的任务
monitor.markCompleted();
System.out.println("主程序结束");
}
}
重要注意事项
必须在线程启动前设置
// 正确方式 Thread t = new Thread(task); t.setDaemon(true); t.start(); // 错误方式 - 会抛出IllegalThreadStateException Thread t = new Thread(task); t.start(); t.setDaemon(true); // 异常!
检查是否为守护线程
public class CheckDaemonDemo {
public static void main(String[] args) {
Thread userThread = new Thread(() -> {
System.out.println("用户线程是否守护: " + Thread.currentThread().isDaemon());
});
userThread.start();
Thread daemonThread = new Thread(() -> {
System.out.println("守护线程是否守护: " + Thread.currentThread().isDaemon());
});
daemonThread.setDaemon(true);
daemonThread.start();
System.out.println("主线程是否守护: " + Thread.currentThread().isDaemon());
}
}
适用场景
- 后台日志记录
- 垃圾回收监控
- 系统资源监控
- 缓存清理
- 定时备份
- 性能统计
守护线程是Java中非常有用的特性,适用于需要持续运行但不需要在程序结束后继续存在的后台服务,创建简单,但要注意必须在start()之前调用setDaemon(true),并且理解JVM退出时不会等待守护线程完成的特点。