Java并發(fā)編程:守護線程
什么是守護線程?
與普通線程相比,守護線程(Daemon Thread)是一種特殊類型的線程。它的特殊性體現(xiàn)在哪里?在理解之前,我們需要先明確一個問題:
Java程序在什么情況下會正常退出?當(dāng)JVM中唯一運行的線程都是守護線程時,Java虛擬機才會退出。這句話源自JDK官方文檔,即:當(dāng)JVM中沒有正在運行的非守護線程時,JVM進(jìn)程會退出。
直接理解可能有些抽象,但通過以下代碼示例會更清晰:
public class Demo1 {
public static void main(String[] args) throws InterruptedException {
// 創(chuàng)建一個用戶線程(非守護線程)
Thread userThread = new Thread(() -> {
// 無限循環(huán)
while (true) {
System.out.println("用戶線程正在運行...");
try {
Thread.sleep(2000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
userThread.start();
Thread.sleep(1000);
// 添加關(guān)閉鉤子
Runtime.getRuntime().addShutdownHook(new Thread(() -> System.out.println("關(guān)閉鉤子正在運行...")));
System.out.println("主線程即將執(zhí)行完畢");
}
}
我們創(chuàng)建了一個用戶線程,其邏輯是無限循環(huán)。運行這段代碼后,猜猜主線程結(jié)束后,JVM進(jìn)程會自動退出嗎?
輸出結(jié)果:
用戶線程正在運行...
主線程即將執(zhí)行完畢
用戶線程正在運行...
用戶線程正在運行...
用戶線程正在運行...
用戶線程正在運行...
...
可以看到,由于后臺始終有一個非守護線程在運行,JVM無法正常自動退出,且關(guān)閉鉤子(ShutdownHook)的邏輯也不會執(zhí)行。程序會每隔2秒持續(xù)輸出“用戶線程正在運行...”。那么,如果是守護線程運行會怎樣?
通過Thread.setDaemon(true)方法將線程設(shè)置為守護線程。代碼如下:
public class Demo2 {
public static void main(String[] args) throws InterruptedException {
// 創(chuàng)建一個守護線程
Thread thread = new Thread(() -> {
// 無限循環(huán)
while (true) {
System.out.println("守護線程正在運行...");
try {
Thread.sleep(2000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
thread.setDaemon(true); // 設(shè)置為守護線程
thread.start();
Thread.sleep(1000);
Runtime.getRuntime().addShutdownHook(new Thread(() -> System.out.println("關(guān)閉鉤子正在運行...")));
System.out.println("主線程即將執(zhí)行完畢");
}
}
再次運行代碼,觀察結(jié)果:
輸出結(jié)果:
守護線程正在運行...
主線程即將執(zhí)行完畢
關(guān)閉鉤子正在運行...
可以看到,當(dāng)主線程退出時,JVM會直接退出,守護線程也隨之終止。即使內(nèi)部有無限循環(huán),守護線程也會立即停止。
守護線程的作用與使用場景
作用
Java引入守護線程的主要目的是提供一種機制來支持后臺任務(wù)的執(zhí)行。守護線程在程序生命周期中扮演輔助角色,為其他線程提供支持和服務(wù)。
以垃圾回收線程(GC)為例,它是一個經(jīng)典的守護線程。當(dāng)程序中不再有任何運行中的用戶線程時,程序也不會再產(chǎn)生垃圾,垃圾回收線程也就無事可做。因此,當(dāng)JVM中只剩下垃圾回收線程時,JVM會自動退出。GC始終在后臺低優(yōu)先級運行,實時監(jiān)控和管理系統(tǒng)中的可回收資源。
使用場景
- 后臺任務(wù)守護線程常用于執(zhí)行與主線程無關(guān)的后臺任務(wù),例如日志記錄、定時任務(wù)、監(jiān)控等。這些任務(wù)可以默默在程序后臺運行,不影響主流程。
- 垃圾回收垃圾回收是JVM的重要功能,負(fù)責(zé)回收無用對象并釋放內(nèi)存。垃圾回收線程是守護線程,會在程序運行時自動執(zhí)行。
- 資源管理守護線程可用于資源管理,例如數(shù)據(jù)庫連接池中的線程池管理器。它可以監(jiān)控空閑連接,若連接長時間未使用,守護線程會自動關(guān)閉連接以避免資源浪費。
- 守護服務(wù)在服務(wù)器應(yīng)用中,守護線程常用于提供服務(wù)。例如,Web服務(wù)器中的守護線程可以監(jiān)聽客戶端請求。當(dāng)所有客戶端連接斷開后,守護線程會自動關(guān)閉服務(wù)器。
注意事項守護線程的終止是不可控的。當(dāng)程序中只剩下守護線程時,它會隨主線程結(jié)束而自動終止。因此,使用守護線程時需確保任務(wù)可中斷或可恢復(fù),且不會影響程序的整體邏輯。