RM新时代网站-首页

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線(xiàn)課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

什么是守護(hù)線(xiàn)程?守護(hù)線(xiàn)程的底層原理和使用示例

CodeSheep ? 來(lái)源:飛天小牛肉 ? 2024-01-05 11:01 ? 次閱讀

大家好,今天這篇文章來(lái)梳理一下有關(guān)守護(hù)線(xiàn)程的相關(guān)問(wèn)題,這也是之前曾經(jīng)有被問(wèn)到過(guò)的面試題,在此之前我們先看一看守護(hù)線(xiàn)程的使用示例。

守護(hù)線(xiàn)程使用示例

我們先來(lái)看看下面這段代碼:

5ef8c72a-ab66-11ee-8b88-92fbcf53809c.png

在上面的示例中,我們創(chuàng)建了一個(gè)守護(hù)線(xiàn)程daemonThread,并將其設(shè)置為守護(hù)線(xiàn)程。

主線(xiàn)程休眠一段時(shí)間后,主線(xiàn)程結(jié)束,程序退出,此時(shí)守護(hù)線(xiàn)程也會(huì)隨之結(jié)束。守護(hù)線(xiàn)程的DaemonTask會(huì)不斷地輸出消息,模擬后臺(tái)任務(wù)的執(zhí)行。

當(dāng)主線(xiàn)程結(jié)束后,你會(huì)注意到守護(hù)線(xiàn)程DaemonTask不再輸出消息,因?yàn)樗?JVM 中止了。

什么是守護(hù)線(xiàn)程

Java 把線(xiàn)程分成兩類(lèi):用戶(hù)線(xiàn)程(User Thread) + 守護(hù)線(xiàn)程(Daemon Thread)

守護(hù)線(xiàn)程的使用有以下要點(diǎn):

當(dāng)程序中所有的用戶(hù)線(xiàn)程執(zhí)行完畢之后,不管守護(hù)線(xiàn)程是否結(jié)束,系統(tǒng)都會(huì)自動(dòng)退出(也就是說(shuō)只要存在一個(gè)用戶(hù)線(xiàn)程在允許,守護(hù)線(xiàn)程就不會(huì)結(jié)束)

守護(hù)線(xiàn)程必須在start啟動(dòng)前通過(guò)setDaemon()方法將狀態(tài)設(shè)置為 true,啟動(dòng)后就不能進(jìn)行設(shè)置,否則報(bào) InterruptedException 異常

守護(hù)線(xiàn)程存在被 JVM 強(qiáng)制終止的風(fēng)險(xiǎn),所以在守護(hù)線(xiàn)程中盡量不去訪(fǎng)問(wèn)系統(tǒng)資源,例如打開(kāi)文件等,因?yàn)樘摂M機(jī)退出時(shí),守護(hù)線(xiàn)程沒(méi)有任何機(jī)會(huì)來(lái)關(guān)閉文件,這會(huì)導(dǎo)致數(shù)據(jù)丟失,所以守護(hù)線(xiàn)程適合執(zhí)行無(wú)需完整執(zhí)行的后臺(tái)任務(wù)。

守護(hù)線(xiàn)程中創(chuàng)建的線(xiàn)程也是守護(hù)線(xiàn)程

JVM 進(jìn)程中的 GC 線(xiàn)程就是一個(gè)守護(hù)線(xiàn)程,這樣設(shè)計(jì)目的很明確,當(dāng)你所有的程序都執(zhí)行完畢了,留著這個(gè) GC 線(xiàn)程就沒(méi)有任何意義了。反過(guò)來(lái)可以設(shè)想,如果把 GC 線(xiàn)程設(shè)計(jì)成非守護(hù)線(xiàn)程,當(dāng)你明確你的程序都執(zhí)行完畢了,但是就是不自動(dòng)退出豈不是很奇怪?

守護(hù)線(xiàn)程的底層原理

守護(hù)線(xiàn)程底層原理是啥?為什么用戶(hù)線(xiàn)程結(jié)束守護(hù)線(xiàn)程就能自動(dòng)退出?(相信很多很多小伙伴遇到這個(gè)題都會(huì)直接懵,屬于低頻但重點(diǎn)的考點(diǎn))

我們看下 JVM 源碼thread.cpp文件,這里是實(shí)現(xiàn)線(xiàn)程的代碼??梢悦げ掠幸欢未a監(jiān)測(cè)著當(dāng)前非守護(hù)線(xiàn)程的數(shù)量,不然怎么知道現(xiàn)在只剩下守護(hù)線(xiàn)程呢?很有可能是在移除線(xiàn)程的方法里面,跟著這個(gè)思路,我們看看該文件的remove()方法。代碼如下

5f164fd4-ab66-11ee-8b88-92fbcf53809c.png

我在里面加了一些注釋?zhuān)梢园l(fā)現(xiàn),果然是我們想的那樣,里面有_number_of_non_daemon_threads記錄著非守護(hù)線(xiàn)程的數(shù)量,而且當(dāng)非守護(hù)線(xiàn)程數(shù)為 1 時(shí),就會(huì)喚醒在destory_vm()方法里面等待的線(xiàn)程,緊接著我們看看destory_vm()代碼,同樣是在thread.cpp文件下:

5f3a45b0-ab66-11ee-8b88-92fbcf53809c.png

可以看到當(dāng)非守護(hù)線(xiàn)程數(shù)量大于 1 時(shí),就一直等待,直到剩下一個(gè)非守護(hù)線(xiàn)程時(shí),就會(huì)在線(xiàn)程執(zhí)行完后,退出 JVM。

這時(shí)候又有一個(gè)點(diǎn)需要搞清楚,就是什么時(shí)候調(diào)用的destroy_vm()方法呢?還是通過(guò)查看代碼以及注釋?zhuān)l(fā)現(xiàn)是在main()方法執(zhí)行完成后觸發(fā)的。

在java.c文件的JavaMain()方法里面,最后執(zhí)行完調(diào)用了LEAVE()方法,該方法調(diào)用了(*vm)->DestroyJavaVM(vm);來(lái)觸發(fā) JVM 退出,最終調(diào)用destroy_vm()方法。

5f4b2e8e-ab66-11ee-8b88-92fbcf53809c.png

總結(jié)下就是:Java 程序在 main 線(xiàn)程執(zhí)行退出時(shí),會(huì)觸發(fā)執(zhí)行 JVM 退出操作(destroy_vm()方法),但是該方法會(huì)等待所有非守護(hù)線(xiàn)程(用戶(hù)線(xiàn)程)都執(zhí)行完,具體原理是使用變量_number_of_non_daemon_threads統(tǒng)計(jì)非守護(hù)線(xiàn)程的數(shù)量,這個(gè)變量在新增線(xiàn)程和刪除線(xiàn)程時(shí)會(huì)做增減操作。

另外衍生一點(diǎn)就是:當(dāng) JVM 退出時(shí),所有還存在的守護(hù)線(xiàn)程會(huì)被拋棄,既不會(huì)執(zhí)行 finally 部分代碼,也不會(huì) catch 異常。這個(gè)很明顯,JVM 都退出了,守護(hù)線(xiàn)程也就不能獨(dú)自存在了。

好了,以上就是今天的內(nèi)容分享,感謝大家的收看,我們下篇見(jiàn)。

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • JAVA
    +關(guān)注

    關(guān)注

    19

    文章

    2966

    瀏覽量

    104700
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4779

    瀏覽量

    68521
  • JVM
    JVM
    +關(guān)注

    關(guān)注

    0

    文章

    158

    瀏覽量

    12220
  • 線(xiàn)程
    +關(guān)注

    關(guān)注

    0

    文章

    504

    瀏覽量

    19675

原文標(biāo)題:京東一面:守護(hù)線(xiàn)程如何實(shí)現(xiàn)的?

文章出處:【微信號(hào):CodeSheep,微信公眾號(hào):CodeSheep】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    Linux守護(hù)進(jìn)程

    這里將上一個(gè)示例程序用syslog服務(wù)進(jìn)行重寫(xiě),其中有區(qū)別的地方用加粗的字體表示,源代碼如下: /* syslog_daemon.c利用syslog服務(wù)的守護(hù)進(jìn)程實(shí)例 */ #include
    發(fā)表于 08-22 09:17

    Linux多線(xiàn)程線(xiàn)程間同步

    、是否為守護(hù)進(jìn)程等??梢允褂肗ULL來(lái)使用默認(rèn)值,通常情況下我們都是使用默認(rèn)值。void *(*func) (void *):函數(shù)指針func,指定當(dāng)新的線(xiàn)程創(chuàng)建之后,將執(zhí)行的函數(shù)。void *arg
    發(fā)表于 12-08 14:14

    Java守護(hù)線(xiàn)程和本地線(xiàn)程的區(qū)別

    java中的線(xiàn)程分為兩種:守護(hù)線(xiàn)程(Daemon)和用戶(hù)線(xiàn)程(User)。
    發(fā)表于 08-07 08:10

    Linux守護(hù)進(jìn)程詳解

    分享到:標(biāo)簽:進(jìn)程控制 Linux 守護(hù)進(jìn)程 子進(jìn)程 7.3 Linux守護(hù)進(jìn)程 7.3.1 守護(hù)進(jìn)程概述 守護(hù)進(jìn)程,也就是通常所說(shuō)的Daemon進(jìn)程,是Linux中的后臺(tái)服務(wù)進(jìn)程。它
    發(fā)表于 10-18 14:24 ?0次下載
    Linux<b class='flag-5'>守護(hù)</b>進(jìn)程詳解

    線(xiàn)程編程之Linux線(xiàn)程編程

    9.2 Linux線(xiàn)程編程 9.2.1 線(xiàn)程基本編程 這里要講的線(xiàn)程相關(guān)操作都是用戶(hù)空間中的線(xiàn)程的操作。在Linux中,一般pthread線(xiàn)程
    發(fā)表于 10-18 15:55 ?3次下載

    線(xiàn)程好還是單線(xiàn)程好?單線(xiàn)程和多線(xiàn)程的區(qū)別 優(yōu)缺點(diǎn)分析

    摘要:如今單線(xiàn)程與多線(xiàn)程已經(jīng)得到普遍運(yùn)用,那么到底多線(xiàn)程好還是單線(xiàn)程好呢?單線(xiàn)程和多線(xiàn)程的區(qū)別又
    發(fā)表于 12-08 09:33 ?8.1w次閱讀

    Jvm工作原理學(xué)習(xí)筆記

    [] args)函數(shù)的class都可以作為JVM實(shí)例運(yùn)行的起點(diǎn) b) 運(yùn)行。main()作為該程序初始線(xiàn)程的起點(diǎn),任何其他線(xiàn)程均由該線(xiàn)程啟動(dòng)。JVM內(nèi)部有兩種線(xiàn)程
    發(fā)表于 04-03 11:03 ?5次下載

    C#多線(xiàn)程技術(shù)

    C#和.NET類(lèi)庫(kù)為開(kāi)發(fā)多線(xiàn)程應(yīng)用程序提供了很方便的支持,本章首先簡(jiǎn)要介紹.NET類(lèi)庫(kù)中的Thread類(lèi)及各種線(xiàn)程支持,再通過(guò)示例說(shuō)明線(xiàn)程使用中需要掌握的規(guī)則,最后論述
    發(fā)表于 04-23 11:32 ?15次下載

    華為P30系列的芯片級(jí)守護(hù)

    芯片級(jí)守護(hù) 華為P30系列如何從底層保證通信安全?
    的頭像 發(fā)表于 08-28 11:18 ?4236次閱讀

    Linux的C編程中多線(xiàn)程如何終止某個(gè)線(xiàn)程示例與要點(diǎn)

    線(xiàn)程被另一個(gè)線(xiàn)程通過(guò) pthread_cancel() 函數(shù)取消,這和通過(guò)kill() 發(fā)送 SIGKILL 信號(hào)類(lèi)似。
    的頭像 發(fā)表于 04-27 13:41 ?3416次閱讀
    Linux的C編程中多<b class='flag-5'>線(xiàn)程</b>如何終止某個(gè)<b class='flag-5'>線(xiàn)程</b><b class='flag-5'>示例</b>與要點(diǎn)

    MFC多線(xiàn)程線(xiàn)程同步

    MFC中有兩類(lèi)線(xiàn)程,分別稱(chēng)之為工作者線(xiàn)程和用戶(hù)界面線(xiàn)程。二者的主要區(qū)別在于工作者線(xiàn)程沒(méi)有消息循環(huán),而用戶(hù)界面線(xiàn)程有自己的消息隊(duì)列和消息循環(huán)。
    發(fā)表于 06-01 17:03 ?0次下載

    為什么說(shuō)線(xiàn)程是輕量級(jí)的概念呢?守護(hù)線(xiàn)程是指什么?

    當(dāng)多個(gè)線(xiàn)程同時(shí)搶多把鎖的時(shí)候就會(huì)出現(xiàn)死鎖的現(xiàn)象。其實(shí)遞歸鎖也不是一個(gè)很好地解決方案,死鎖現(xiàn)象的發(fā)生不是互斥鎖的原因,而是程序猿/媛的邏輯出現(xiàn)了問(wèn)題。
    的頭像 發(fā)表于 08-19 10:39 ?2066次閱讀
    為什么說(shuō)<b class='flag-5'>線(xiàn)程</b>是輕量級(jí)的概念呢?<b class='flag-5'>守護(hù)</b><b class='flag-5'>線(xiàn)程</b>是指什么?

    什么是線(xiàn)程線(xiàn)程池中線(xiàn)程實(shí)現(xiàn)復(fù)用的原理

    一般建議自定義線(xiàn)程工廠(chǎng),構(gòu)建線(xiàn)程的時(shí)候設(shè)置線(xiàn)程的名稱(chēng),這樣就在查日志的時(shí)候就方便知道是哪個(gè)線(xiàn)程執(zhí)行的代碼。
    發(fā)表于 01-29 13:44 ?1746次閱讀

    線(xiàn)程線(xiàn)程

    線(xiàn)程池通常用于服務(wù)器應(yīng)用程序。 每個(gè)傳入請(qǐng)求都將分配給線(xiàn)程池中的一個(gè)線(xiàn)程,因此可以異步處理請(qǐng)求,而不會(huì)占用主線(xiàn)程,也不會(huì)延遲后續(xù)請(qǐng)求的處理
    的頭像 發(fā)表于 02-28 09:53 ?786次閱讀
    多<b class='flag-5'>線(xiàn)程</b>之<b class='flag-5'>線(xiàn)程</b>池

    線(xiàn)程池的線(xiàn)程怎么釋放

    線(xiàn)程分組看,pool名開(kāi)頭線(xiàn)程占616條,而且waiting狀態(tài)也是616條,這個(gè)點(diǎn)就非??梢闪?,我斷定就是這個(gè)pool開(kāi)頭線(xiàn)程池導(dǎo)致的問(wèn)題。我們先排查為何這個(gè)線(xiàn)程池中會(huì)有600+的
    發(fā)表于 07-31 10:49 ?2274次閱讀
    <b class='flag-5'>線(xiàn)程</b>池的<b class='flag-5'>線(xiàn)程</b>怎么釋放
    RM新时代网站-首页