Java 多線程幾乎是面試必問問題,由于多線程涉及的方面非常多,因此分為多篇文章對其講述,方便觀看瀏覽。
線程狀態(tài)
線程的狀態(tài)轉(zhuǎn)換是線程控制的基礎(chǔ)。線程狀態(tài)總的可分為五大狀態(tài):
New
線程剛剛創(chuàng)建初始化,調(diào)用 start 接口之前
RUNNABLE
線程調(diào)用 start 接口之后,處以可以執(zhí)行狀態(tài),等待被系統(tǒng)調(diào)度和正在執(zhí)行中都是處于這個狀態(tài)
BLOCKED
線程如果處于等待獲取 Monitor 鎖的狀態(tài)
WAITING
處于這個狀態(tài)的線程,說明正在無期限地等待其他線程的某些特定動作
TIMED_WAITING
這個狀態(tài)下的線程,在有限的時間內(nèi)等待其他線程的某些特定動作
TERMINATED
線程執(zhí)行完畢,已經(jīng)退出
狀態(tài)轉(zhuǎn)移
線程各個狀態(tài)之間的轉(zhuǎn)移如下圖所示:
其中以下狀態(tài)的轉(zhuǎn)移需要關(guān)注下:
New -> RUNNABLE
線程實例調(diào)用 start 方法即可進入可運行狀體。
如果正在執(zhí)行的線程運行到 yield 方法,則讓出 CPU 時間片,但狀態(tài)還是 RUNNABLE。
RUNNABLE -> BLOCKED
通常調(diào)用 synchronized 方法,或者嘗試進入 synchronized 程序時,又沒搶占到 Object 的 Monitor 鎖時,會產(chǎn)生這種狀態(tài)遷移。
RUNNABLE -> WAITING
線程調(diào)用 Object.wait() / LockSupport.park() / Thread.join() 方法。
其中 join 方法是 synchronized 方法,內(nèi)部調(diào)用當(dāng)前線程對象的 wait 方法。
RUNNABLE -> TIMED_WAITING
情況和 RUNNABLE -> WAITING 類似,但是增加了 Thread.sleep 情況,調(diào)用 sleep 時 不會釋放 當(dāng)前線程搶占到的 Monitor 鎖,所以當(dāng) sleep 結(jié)束后,依舊進入 RUNNABLE 狀態(tài)。
WAITING -> RUNNABLE
其他線程調(diào)用 Object.notify() / Object.notifyAll() 時,某等待線程被喚醒,同時搶到等待對象的 Monitor鎖。
WAITING -> BLOCKED
其他線程調(diào)用 Object.notify() / Object.notifyAll() 時,某等待線程被喚醒,同時沒有搶到等待對象的 Monitor鎖,只能被阻塞等待其他線程釋放鎖。