我麻了,京東一面:守護(hù)線程如何實(shí)現(xiàn)的?
守護(hù)線程使用示例
看下面這段代碼:
在上面的示例中,我們創(chuàng)建了一個(gè)守護(hù)線程daemonThread,并將其設(shè)置為守護(hù)線程。主線程休眠一段時(shí)間后,主線程結(jié)束,程序退出,此時(shí)守護(hù)線程也會(huì)隨之結(jié)束。守護(hù)線程的DaemonTask會(huì)不斷地輸出消息,模擬后臺(tái)任務(wù)的執(zhí)行。當(dāng)主線程結(jié)束后,你會(huì)注意到守護(hù)線程DaemonTask不再輸出消息,因?yàn)樗?JVM 中止了。
什么是守護(hù)線程
Java 把線程分成兩類:用戶線程(User Thread) + 守護(hù)線程(Daemon Thread)守護(hù)線程的使用有以下要點(diǎn):- 當(dāng)程序中所有的用戶線程執(zhí)行完畢之后,不管守護(hù)線程是否結(jié)束,系統(tǒng)都會(huì)自動(dòng)退出(也就是說(shuō)只要存在一個(gè)用戶線程在允許,守護(hù)線程就不會(huì)結(jié)束)
- 守護(hù)線程必須在
start啟動(dòng)前通過(guò)setDaemon()方法將狀態(tài)設(shè)置為 true,啟動(dòng)后就不能進(jìn)行設(shè)置,否則報(bào) InterruptedException 異常 - 守護(hù)線程存在被 JVM 強(qiáng)制終止的風(fēng)險(xiǎn),所以在守護(hù)線程中盡量不去訪問(wèn)系統(tǒng)資源,例如打開文件等,因?yàn)樘摂M機(jī)退出時(shí),守護(hù)線程沒(méi)有任何機(jī)會(huì)來(lái)關(guān)閉文件,這會(huì)導(dǎo)致數(shù)據(jù)丟失,所以守護(hù)線程適合執(zhí)行無(wú)需完整執(zhí)行的后臺(tái)任務(wù)。
- 守護(hù)線程中創(chuàng)建的線程也是守護(hù)線程
守護(hù)線程的底層原理
守護(hù)線程底層原理是啥?為什么用戶線程結(jié)束守護(hù)線程就能自動(dòng)退出?(相信很多很多小伙伴遇到這個(gè)題都會(huì)直接懵,屬于低頻但重點(diǎn)的考點(diǎn))我們看下 JVM 源碼thread.cpp文件,這里是實(shí)現(xiàn)線程的代碼。可以盲猜有一段代碼監(jiān)測(cè)著當(dāng)前非守護(hù)線程的數(shù)量,不然怎么知道現(xiàn)在只剩下守護(hù)線程呢?很有可能是在移除線程的方法里面,跟著這個(gè)思路,我們看看該文件的remove()方法。代碼如下
我在里面加了一些注釋,可以發(fā)現(xiàn),果然是我們想的那樣,里面有_number_of_non_daemon_threads記錄著非守護(hù)線程的數(shù)量,而且當(dāng)非守護(hù)線程數(shù)為 1 時(shí),就會(huì)喚醒在destory_vm()方法里面等待的線程,緊接著我們看看destory_vm()代碼,同樣是在thread.cpp文件下:
可以看到當(dāng)非守護(hù)線程數(shù)量大于 1 時(shí),就一直等待,直到剩下一個(gè)非守護(hù)線程時(shí),就會(huì)在線程執(zhí)行完后,退出 JVM。這時(shí)候又有一個(gè)點(diǎn)需要搞清楚,就是什么時(shí)候調(diào)用的destroy_vm()方法呢?還是通過(guò)查看代碼以及注釋,發(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()方法。
總結(jié)下就是: Java 程序在 main 線程執(zhí)行退出時(shí),會(huì)觸發(fā)執(zhí)行 JVM 退出操作(destroy_vm()方法),但是該方法會(huì)等待所有非守護(hù)線程(用戶線程)都執(zhí)行完,具體原理是使用變量_number_of_non_daemon_threads統(tǒng)計(jì)非守護(hù)線程的數(shù)量,這個(gè)變量在新增線程和刪除線程時(shí)會(huì)做增減操作。另外衍生一點(diǎn)就是:當(dāng) JVM 退出時(shí),所有還存在的守護(hù)線程會(huì)被拋棄,既不會(huì)執(zhí)行 finally 部分代碼,也不會(huì) catch 異常。這個(gè)很明顯,JVM 都退出了,守護(hù)線程還能獨(dú)自存在?

往 期 推 薦
1、老黃贏麻了!英偉達(dá)H100訂單排到24年,馬斯克都坐不住了
2、明明是工作經(jīng)驗(yàn)越久越吃香,為什么程序員卻不是?
3、中國(guó)的獨(dú)立開發(fā)者都在開發(fā)些什么?
5、Linus 親自 review 代碼,希望平息關(guān)于 Bcachefs 文件系統(tǒng)的 “內(nèi)斗”
點(diǎn) 分 享
點(diǎn) 收 藏
點(diǎn) 點(diǎn) 贊
點(diǎn)在看
評(píng)論
圖片
表情
