關於java線程狀態的一點小小的疑惑

 

事情是這樣了,一個月黑風高的晚上,窗外的冷空氣是那麼的可口解渴,讓人沉浸地無法自拔,人們都沉沉的睡去了,它正貪婪地,,,,突然,,,,

我這kafka不消費數據,是這個問題引起的?看着不像,正說着發來了線程堆棧

看着不像kafkaConsumer的線程棧啊,其實另一張圖有就不發了沒啥看頭

如此如此

這般這般

,,,,,,,,,,,,,,,,,,,,,,

最後同事那邊說是卡在與數據庫通信上了也不是kafka消費的問題

但是,我看那個java線程的函數調用棧跟狀態有點怪啊,明明是調用socket的read接口,top下任務狀態又是S,除非是非阻塞的(如果是阻塞的strace會卡住),我想也沒有人會搞個非阻塞的輪詢加個sleep吧!既然是阻塞IO,這個java線程的狀態不該是RUNNABLE,應該是BLOCKED阻塞狀態纔對啊,被read block住纔對

在我的記憶裏一個正常運行的linux任務基本上只要不運行卡住了大多數就是STD這三個狀態,STD都稱爲阻塞狀態,但我隱約記得以前看jstack時看到java線程有個BLOCKED狀態,這個java線程是在read socket時卡住了與之對應的linux任務狀態是S,那這個java線程不該是BLOCKED狀態?都阻塞了跑不了了,怎麼還成了RUNNABLE狀態

於是帶着疑惑來看看這個RUNNABLE狀態到底是個哈

如上圖java線程一共有6種狀態

NEW:創建了一個線程但還未調用start啓動

RUNNABLE:java任務的字節碼正在被jvm的字節碼解釋器解釋執行(什麼時候纔不在jvm上執行?等待monitor lock,調用wait,join,被LockSupport.park時?)或等待 “操作系統的資源“,這個”操作系統的資源“是指什麼?除了等待被調度到物理CPU上運行外,
我想是不是還應當包括jvm調用os提供的接口?如accept一個新連接,從磁盤,網絡讀寫數據等,
調用os的接口也是所謂的 “操作系統的資源“ 的一部分?就算調用的接口將會阻塞與之對應的os線程,
對jvm而言這個線程還是可運行的,因爲調用一個os阻塞的系統調用而被阻塞,這對jvm而言是無法感知的,
而因jdk的LockSupport.park,或jvm的monitor lock被阻塞,都是在jvm的管控下,
因此可以在阻塞線程前根據調用的接口修改與之對應的java線程的狀態,java線程的阻塞是jvm操作的,
os線程的阻塞是os操作的,java的線程模型是1:1的,一個java線程對應一個os線程,jvm只是把os線程封裝了一下 


 

BLOCKED:線程等待獲取monitor lock時的狀態

WAITTING:線程wait ,join或被LockSupport.park等待被喚醒時的狀態

對於BLOCKED與WAITTING狀態的java線程,在操作系統原理中都稱爲阻塞態,不知道爲什麼還要做區分

TIMED_WAITTING:線程sleep,wait,join,LockSupport.park帶超時等待被喚醒時的狀態

TERMINATED:線程運行結束退出

因此java線程因等待IO而被阻塞時狀態是RUNNABLE而不是BLOCKED,java線程只有被特定的接口操作後纔會轉變爲特定的狀態,就算被一個os的系統調用阻塞,一個的RUNNABLE狀態的java線程仍是RUNNABLE,java線程狀態與之對應的os線程狀態並沒有多大關係,其狀態是獨立於os線程的,要想知道一個處於RUNNABLE狀態的java線程到底是卡住了還是正在物理CPU上運行,還是要通過宿主操作系統才能知道

那麼問題來了STW時,java業務線程的狀態是什麼?

我猜是RUNNABLE

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章