- Java并發編程深度解析與實戰
- 譚鋒(Mic)
- 960字
- 2022-05-10 18:39:15
1.10 揭秘守護線程
在Java中,線程可以分為兩類:
? 用戶線程。
? 守護線程。
從使用方法來說,它們兩個唯一的區別在于,守護線程在啟動之前,需要通過setDaemon(true)方法進行設置,代碼如下。

從功能層面來說,守護線程和用戶線程最大的區別在于,守護線程不會影響JVM進程的退出,而用戶線程在有任務沒有執行完成前,JVM進程不會退出直到所有用戶線程運行結束。
下面我們通過一個案例來分析,代碼如下。


在DaemonThreadExample這個案例中,我們在main()方法中創建了一個thread線程,該線程通過一個while(true)循環不斷運行,避免該線程執行結束(默認情況下主線程中創建的所有線程都是用戶線程)。接著啟動該線程讓它執行,在main()方法最后打印一段話表示主線程結束。
這段代碼的輸出結果如下,可以發現即便main()方法運行結束,該JVM進程也是處于存活狀態,而且用戶線程一直處于運行中。也就是說在一個JVM進程中,只要有一個用戶線程在運行,該JVM進程就無法正常退出。

于是我們對上述代碼進行修改,把thread線程設置為守護線程,代碼如下。


Runtime.getRuntime().addShutdownHook()可以用來注冊JVM關閉的鉤子,這個鉤子可以在程序正常退出、系統關閉、OOM宕機時被回調。
上述程序運行結果如下,可以發現雖然thread線程沒有運行完,但當main()方法運行結束后,該JVM進程仍然退出了。

1.10.1 守護線程的應用場景
可能讀者會覺得守護線程看起來好像沒什么用?但是實際上它的作用很大。
? 比如在JVM中垃圾回收器就采用了守護線程,如果一個程序中沒有任何用戶線程,那么就不會產生垃圾,垃圾回收器也就不需要工作了。
? 在一些中間件的心跳檢測、事件監聽等涉及定時異步執行的場景中也可以使用守護線程,因為這些都是在后臺不斷執行的任務,當進程退出時,這些任務也不需要存在,而守護線程可以自動結束自己的生命周期。
從這些實際場景中可以看出,對于一些后臺任務,當不希望阻止JVM進程結束時,可以采用守護線程。
1.10.2 守護線程使用注意事項
平時我們用到的守護線程的場景不多,大部分場景都集成在各種中間件中。對業務開發來說一般會用線程池,而線程池默認都是非守護線程,并不需要我們專門去設置線程的守護類型,守護線程的使用需要注意以下兩點。
? 在Java中,線程的狀態是自動繼承的。也就是說,如果一個線程是用戶線程,那么它創建的子線程默認都是用戶線程;如果一個線程是守護線程,那么它創建的子線程默認就是守護線程。
? thread.setDaemon(true)必須在start()方法啟動之前調用,因為通常我們會將一個正在運行的線程設置為守護線程。
- Spring Boot 2實戰之旅
- UI圖標創意設計
- OpenStack Cloud Computing Cookbook(Third Edition)
- Java游戲服務器架構實戰
- Learning Apache Kafka(Second Edition)
- Node.js全程實例
- Android驅動開發權威指南
- 持續集成與持續交付實戰:用Jenkins、Travis CI和CircleCI構建和發布大規模高質量軟件
- Learning AWS
- 鴻蒙OS應用編程實戰
- Python 快速入門(第3版)
- Deep Learning for Natural Language Processing
- Learning TypeScript
- 歐姆龍PLC編程指令與梯形圖快速入門
- Qt編程快速入門