官术网_书友最值得收藏!

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()方法啟動之前調用,因為通常我們會將一個正在運行的線程設置為守護線程。

主站蜘蛛池模板: 铁力市| 班玛县| 曲阳县| 琼中| 齐河县| 扶风县| 砀山县| 黔西县| 都江堰市| 莱州市| 汝阳县| 海阳市| 扎兰屯市| 凌云县| 海丰县| 湘潭市| 凌云县| 田阳县| 宽城| 堆龙德庆县| 滦南县| 宽甸| 万载县| 叶城县| 平江县| 伊春市| 大新县| SHOW| 荆州市| 土默特左旗| 赤水市| 长乐市| 镇远县| 武山县| 钟祥市| 满城县| 青田县| 新余市| 海口市| 江孜县| 怀柔区|