面試官:都說阻塞 I/O 模型將會使執行緒休眠,為什麼 Java 執行緒狀態卻是 RUNNABLE?
摘要: 原創出處 https://studyidea.cn 「公眾號:程式通事 」歡迎關注和轉載,保留摘要,謝謝!
使用 Java 阻塞 I/O 模型讀取資料,將會導致執行緒阻塞,執行緒將會進入休眠,從而讓出 CPU 的執行權,直到資料讀取完成。這個期間如果使用 jstack 檢視執行緒狀態,卻可以發現Java 執行緒狀態是處於 RUNNABLE,這就和上面說的存在矛盾,為什麼會這樣?
上面的矛盾其實是混淆了作業系統執行緒狀態與 Java 執行緒狀態。這裡說的執行緒阻塞進入休眠狀態,其實是作業系統層面執行緒實際狀態。而我們使用 jstack 檢視的執行緒狀態卻是 JVM 中的執行緒狀態。
執行緒是作業系統中一種概念,Java 對其進行了封裝,Java 執行緒本質上就是作業系統的中執行緒,其狀態與作業系統的狀態大致相同,但還是存在一些區別。
下面首先來看我們熟悉的 Java 執行緒狀態。
Java 執行緒狀態
Java 執行緒狀態定義在 Thread.State
列舉中,使用 thread#getState
方法可以獲取當前執行緒的狀態。
Thread.State
狀態如下圖:
可以看到 Java 執行緒總共存在 6 中狀態,分別為:
- NEW(初始狀態)
- RUNNABLE(執行狀態)
- BLOCKED(阻塞狀態)
- WATTING(等待狀態)
- TIMED_WAITING(限時等待狀態)
- TERMINATED(終止狀態)
NEW(初始狀態)與 RUNNABLE(執行狀態)
每個使用 new Thread()
剛創建出執行緒例項狀態處於 NEW 狀態,一旦呼叫 thread.start()
RUNNABLE(執行狀態) 與 BLOCKED(阻塞狀態)
RUNNABLE 狀態的執行緒在進入由 synchronized
修飾的方法或程式碼塊前將會嘗試獲取一把隱式的排他鎖,一旦獲取不到,執行緒狀態將會變成 BLOCKED,等待獲取鎖。一旦有其他執行緒釋放這把鎖,執行緒成功搶到該鎖,執行緒狀態就將會從 BLOCKED 轉變為 RUNNABLE 狀態。
RUNNABLE(執行狀態) 與 WATTING(等待狀態)
處於 WATTING 狀態的執行緒將會一直處於無限期的等待狀態,需要等待其他執行緒喚醒。總共存在三種方法將會使執行緒從 RUNNABLE 變成 WATTING。
Object#wait
執行緒在獲取到 synchronized
隱式鎖後,顯示的呼叫 Object#wait()
方法。這種情況下該執行緒將會讓出隱式鎖,一旦其他執行緒獲取到該鎖,且呼叫了 Object.notify()
或object.notifyAll()
,執行緒將會喚醒,然後變成 RUNNABLE。
Thread#join
join
方法是一種執行緒同步方法。假設我們在 main 方法中執行 Thread A.join() 方法,main 執行緒狀態就會變成 WATTING。直到 A 執行緒執行完畢,main 執行緒才會再變成 RUNNABLE。
LockSupport#park()
LockSupport 是 JDK 併發包裡重要物件,很多鎖的實現都依靠該物件。一旦呼叫 LockSupport#park()
,執行緒就將會變為 WATTING 狀態。如果需要喚醒執行緒就需要呼叫 LockSupport#unpark,然後執行緒狀態重新變為 RUNNABLE。
RUNNABLE(執行狀態) 與 TIMED_WAITING(限時等待狀態)
TIMED_WAITING 與 WATTING 功能一樣,只不過前者增加限時等待的功能,一旦等待時間超時,執行緒狀態自動變為 RUNNABLE。以下幾種情況將會觸發這種狀態:
Thread#sleep(long millis)
- 佔有 synchronized 隱式鎖的執行緒呼叫
Object.wait (long timeout)
方法 Thread#join (long millis)
LockSupport#parkNanos (Object blocker, long deadline)
LockSupport#parkUntil (long deadline)
RUNNABLE(執行狀態)與 TERMINATED(終止狀態)
執行緒一旦執行結束或者執行緒執行過程發生異常且未正常捕獲處理,狀態都將會自動變成 TERMINATED。
Java 執行緒 6 種狀態看起來挺複雜的,但其實上面 BLOCKED,WATTING,TIMED_WAITING,都會使執行緒處於休眠狀態,所以我們將這三類都歸類為休眠狀態。這麼分類的話,Java 執行緒生命週期就可以簡化為下圖:
通用作業系統執行緒狀態
上面講完 Java 系統的執行緒狀態,我們來看下通用作業系統的執行緒狀態。作業系統執行緒狀態可以分為初始狀態,可執行狀態,執行狀態,休眠狀態以及終止狀態,如下圖:
這 5 中狀態詳細情況如下:
- 初始狀態,這時候執行緒剛被建立,還不能分配 CPU 。
- 可執行狀態,執行緒等待系統分配 CPU ,從而執行任務。
- 執行狀態,作業系統將 CPU 分配給執行緒,執行緒執行任務。
- 休眠狀態,執行狀態下的執行緒如果呼叫阻塞 API,如阻塞方式讀取檔案, 執行緒狀態就將變成休眠狀態。這種情況下,執行緒將會讓出 CPU 使用權。休眠結束,執行緒狀態將會先變成可執行狀態。
- 執行緒執行結束或者執行過程發生異常將會使執行緒進入終止狀態,這個狀態下執行緒使命已經結束。
對比兩者執行緒狀態
比較 Java 執行緒與作業系統執行緒,可以發現 Java 執行緒狀態沒有可執行狀態。也就是說 Java 執行緒 RUNNABLE 狀態包括了作業系統的可執行狀態與執行狀態。一個處於 RUNNABLE 狀態 Java 執行緒,在作業系統層面狀態可能為可執行狀態,正在等待系統分配 CPU 使用權。
另外 Java 執行緒細分了作業系統休眠狀態,分成了 BLOCKED,WATTING,TIMED_WAITING 三種。
當執行緒呼叫阻塞式 API,執行緒進入休眠狀態,這裡指的是作業系統層面的。從 JVM 層面,Java 執行緒狀態依然處於 RUNNABLE 狀態。JVM 並不關心作業系統執行緒實際狀態。從 JVM 看來等待 CPU 使用權(作業系統執行緒狀態為可執行狀態)與等待 I/O (作業系統執行緒狀態處於休眠狀態)沒有區別,都是在等待某種資源,所以都歸入 RUNNABLE 狀態。
其他 Java 執行緒狀態與操作執行緒狀態類似。
面試官:都說阻塞 I/O 模型將會使執行緒休眠,為什麼 Java 執行緒狀態卻是 RUNNABLE?
相關推薦
面試官:都說阻塞 I/O 模型將會使執行緒休眠,為什麼 Java 執行緒狀態卻是 RUNNABLE?
摘要: 原創出處 https://studyidea.cn 「公眾號:程式通事 」歡迎關注和轉載,保留摘要,謝謝! 使用 Java 阻塞 I/O 模型讀取資料,將會導致執行緒阻塞,執行緒將會進入休眠,從而讓出 CPU 的執行權,直到資料讀取完成。這個期間如果使用 jstack 檢視執行緒狀態,卻可以發
socket阻塞與非阻塞,同步與非同步、I/O模型(轉載只為查閱方便,若有侵權,立刪)
socket阻塞與非阻塞,同步與非同步 作者:huangguisu 1. 概念理解 在進行網路程式設計時,我們常常見到同步(Sync)/非同步(Async),阻塞(Block)/非阻塞(Unbl
理解Node.js的非同步非阻塞I/O模型
對後臺伺服器程式設計不清楚,通過在網上查資料也就大概有寫了解。 Apache對併發請求的處理方式是,對每個請求就建立一個執行緒處理,這個執行緒是堵塞的。因為執行緒的是佔用記憶體的,所以一臺伺服器能支援的併發執行緒量是有限的。 node.js是單執行緒的模型,但是執行緒是非同
網絡I/O模型---同步異步阻塞非阻塞之惑
本質 結果 順序執行 其中 ges package 混合 signal 同時 網絡I/O模型 人多了,就會有問題。web剛出現的時候,光顧的人很少。近年來網絡應用規模逐漸擴大,應用的架構也需要隨之改變。C10k的問題,讓工程師們需要思考服務的性能與應用的並發能力。 網絡應
socket阻塞與非阻塞 同步與非同步 I/O模型
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!  
Windows I/O模型、同步/非同步、阻塞/非阻塞
同步 所謂同步,就是在發出一個功能呼叫時,在沒有得到結果之前,該呼叫就不返回。按照這個定義,其實絕大多數函式都是同步呼叫(例如sin, isdigit等)。但是一般而言,我們在說同步、非同步的時候,特指那些需要其他部件協作或者需要一定時間完成的任務。最常見的例子就是 SendMessag
聊聊阻塞與非阻塞、同步與非同步、I/O模型
1. 概念理解 在進行網路程式設計時,我們常常見到同步(Sync)/非同步(Async),阻塞(Block)/非阻塞(Unblock)四種呼叫方式: 同步/非同步主要針對C端: 同步: 所謂同步,就是在c端發出一個功能呼叫時,在沒有得到結果之前,該呼叫就不返回。也就是必須一件一件事做,等前一件做完了才能做
面試知識點NIO-非阻塞I/O(轉)
原文:NIO的使用http://hi.baidu.com/zbzb/blog/item/ba775eee89e2b2fbb3fb9515.html使用Java NIO編寫高效能的伺服器http://www.javaeye.com/post/192013一. 介紹NIONIO包
網路程式設計中阻塞與非阻塞、同步與非同步、I/O模型的理解
1. 概念理解 在進行網路程式設計時,我們常常見到同步(Sync)/非同步(Async),阻塞(Block)/非阻塞(Unblock)四種呼叫方式:同步:所謂同步,就是在發出一個功能呼叫時,在沒有得到結果之前,該呼叫就不返回。也就是必須一件一件事做,等前一件做完了才能做下一件事。 例如
I/O模型:同步I/O和非同步I/O,阻塞I/O和非阻塞I/O
同步(synchronous) IO和非同步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blocking)IO分別是什麼,到底有什麼區別? 這個問題其實不同的人給出的答案都可能不同,在大部分的博文中(包括WIKI在內),我們很可能
【轉】【NIO】Java面試高階篇—Java NIO:淺析I/O模型面試題15期
在進入Java NIO程式設計之前,我們今天先來討論一些比較基礎的知識:I/O模型。本文先從同步和非同步的概念 說起,然後接著闡述了阻塞和非阻塞的區別,接著介紹了阻塞IO和非阻塞IO的區別,然後介紹了同步IO和非同步IO的區別,接下來介紹了5種IO模型,最後介紹了兩種和高
socket阻塞與非阻塞,同步與非同步、I/O模型
1. 概念理解 在進行網路程式設計時,我們常常見到同步(Sync)/非同步(Async),阻塞(Block)/非阻塞(Unblock)四種呼叫方式: 同步/非同步主要針對C端: 同步:所謂同步,就是在c端發出一個功能呼叫時,在沒有得到結果之前,該
簡明網路I/O模型---同步非同步阻塞非阻塞之惑
網路I/O模型 人多了,就會有問題。web剛出現的時候,光顧的人很少。近年來網路應用規模逐漸擴大,應用的架構也需要隨之改變。C10k的問題,讓工程師們需要思考服務的效能與應用的併發能力。 網路應用需要處理的無非就是兩大類問題,網路I/O,資料計算。相對於後者,網路I/O的延
I/O 模型,阻塞非阻塞,同步非同步
一個IO操作,需要2步。 以read為例, read --> sys_Read --> 驅動中的buffer資料 OR 網路中的udp/tcp報文 等等 同步/非同步 是否阻塞在第二步。 也就是 sys_Read -->
linux下的 I/O 模型,同步/非同步,阻塞/非阻塞介紹
同步/非同步,阻塞/非阻塞 一提到網路程式設計中的 I/O 模型,總會涉及到這幾個概念,但是這幾個名詞又容易混淆,於是我想總結一下。 我們先看一下在《UNIX網路程式設計:卷一》中講到的5中 UNIX 下的 I/O 模型,分別是 阻塞式 I/O 非阻塞式
網路I/O模型---同步非同步阻塞非阻塞之惑
網路I/O模型---同步非同步阻塞非阻塞之惑 網路I/O模型 人多了,就會有問題。web剛出現的時候,光顧的人很少。近年來網路應用規模逐漸擴大,應用的架構也需要隨之改變。C10k的問題,讓工程師們需要思考服務的效能與應用的併發能力。 網路應用需要處理的無非就是兩大類問題,網
Linux下五種I/O模型詳解(阻塞IO、非阻塞IO、IO複用、訊號驅動、非同步IO)
文章轉載自微信公眾號:漫話程式設計 1 什麼是I/O 程式是由資料+指令構成的,執行程式的過程可以分成下面這幾步: 1.將程式碼載入到記憶體中,逐條執行記憶體中的程式碼 2.在執行程式碼的過程中,可能需要對檔案的讀寫,即將檔案輸入(Input)
[轉]簡明網路I/O模型---同步非同步阻塞非阻塞之惑
網路I/O模型 人多了,就會有問題。web剛出現的時候,光顧的人很少。近年來網路應用規模逐漸擴大,應用的架構也需要隨之改變。C10k的問題,讓工程師們需要思考服務的效能與應用的併發能力。 網路應用需要處理的無非就是兩大類問題,網路I/O,資料計算。相對於後者,網路I/O的延遲,給應用帶來的效能瓶頸大於
socket同步和非同步、阻塞和非阻塞、I/O模型
在進行網路程式設計時,常常見到同步(Sync)/非同步(Async),阻塞(Block)/非阻塞(Unblock)四種呼叫方式同步/非同步主要針對C端: 同步:c端發出一個功能呼叫時,在沒有得到結果之前,c端死等結果例如:普通B/S模式(同步):提交請求->等待伺服器處理->處理完畢返回 這個期間
Java NIO:淺析I/O模型
問題 區別 ror borde ket .cn dex selector 以及 學習Java的同學註意了!!! 學習過程中遇到什麽問題或者想獲取學習資源的話,歡迎加入Java學習交流群:618528494 我們一起學Java! 也許很多朋友在學習NIO的時候都會