您好,登錄后才能下訂單哦!
這篇文章主要介紹“java線程有多少種狀態(tài)”,在日常操作中,相信很多人在java線程有多少種狀態(tài)問題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”java線程有多少種狀態(tài)”的疑惑有所幫助!接下來,請(qǐng)跟著小編一起來學(xué)習(xí)吧!
人有生老病死。同樣的,線程有自己的生命周期。在 Java 中線程的生命周期中一共有 6 種狀態(tài):
New(新創(chuàng)建)
Runnable(可運(yùn)行)
Blocked(被阻塞)
Waiting(等待)
Timed Waiting(計(jì)時(shí)等待)
Terminated(被終止)
查看 Thread 類的源碼時(shí),內(nèi)部還定義了這樣一個(gè)枚舉類。這個(gè)枚舉類定義的就是線程的狀態(tài),源碼如下:
public enum State { NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED; }
PS:線程在任何時(shí)刻只可能處于以上 6 種的其中 1 種狀態(tài),我們可以調(diào)用 getState () 查看線程的狀態(tài)。
我們知道線程有 6 種狀態(tài)。然而,它是如何切換的呢?狗哥根據(jù)自己的理解做了一張圖,接下來將根據(jù)這張圖詳細(xì)了解下線程狀態(tài)的切換。
線程的 6 種狀態(tài)
先注意 NEW 狀態(tài):線程被 NEW 出來,但還沒調(diào)用 start 方法時(shí),就處于這種狀態(tài)。一旦調(diào)用了 start 方法也就進(jìn)入了 RUNNABLE 狀態(tài)。
處于 RUNNABLE 的線程,比較特殊。它還分兩種狀態(tài):Running 和 Ready。也就是說,Java 中處于 Runnable 狀態(tài)的線程有可能正在執(zhí)行,也有可能沒有正在執(zhí)行,正在等待被分配 CPU 資源。
因此,我們可以推斷出,一個(gè)處于 Runnable 狀態(tài)的線程,當(dāng)它運(yùn)行到任務(wù)的一半時(shí),執(zhí)行該線程的 CPU 被調(diào)度去做其他事情,則該線程暫時(shí)不運(yùn)行。但是,它的狀態(tài)依然不變,還是 Runnable,因?yàn)樗锌赡茈S時(shí)被調(diào)度回來繼續(xù)執(zhí)行任務(wù)。
也就是說:處于 Runnable 狀態(tài)的線程并不一定在運(yùn)行。這點(diǎn)在面試中常問,小伙伴們要注意了。
再來看看最簡(jiǎn)單的 Blocked 狀態(tài),從 Runnable 進(jìn)入 Blocked 只有一種可能:就是進(jìn)入 synchronized 關(guān)鍵字保護(hù)的代碼,但是沒有獲取到 monitor 鎖。
線程的 6 種狀態(tài)
再來,看圖的右側(cè),Blocked ----> Runnable 狀態(tài):當(dāng)處于 Blocked 狀態(tài)的線程獲取到鎖。
線程從 Runnable 進(jìn)入 Waiting 狀態(tài),有三種可能性:
沒有設(shè)置 Timeout 參數(shù)的 Object.wait () 方法。
沒有設(shè)置 Timeout 參數(shù)的 Thread.join () 方法。
LockSupport.park () 方法。
上面我們知道,線程進(jìn)入 Blocked 狀態(tài)只可能是:進(jìn)入 synchronized 保護(hù)的代碼,但是沒獲取到 monitor 鎖。然而,Java 中還有很多鎖,比如:ReentrantLock。線程在獲取這種鎖時(shí),沒有搶到就會(huì)進(jìn)入 Waiting 狀態(tài),因?yàn)樗举|(zhì)上是調(diào)用了 LockSupport.park () 方法。
同樣的,調(diào)用 Object.wait () 和 Thread.join () 也會(huì)讓線程進(jìn)入等待狀態(tài)。
Blocked 與 Waiting 的區(qū)別是:Blocked 在等待其他線程釋放 monitor 鎖,而 Waiting 則是在等待某個(gè)條件,比如 join 的線程執(zhí)行完畢,或者是 notify ()/notifyAll ()。
線程的 6 種狀態(tài)
看 Waiting 右側(cè),Waiting ----> Runnable:1、當(dāng)執(zhí)行了 LockSupport.unpark (),2、join 的線程運(yùn)行結(jié)束,3、被中斷
看 Waiting 右側(cè),Waiting ----> Blocked:我們看圖可以知道其他線程調(diào)用 notify () 或 notifyAll () 來喚醒處于 Waiting 的線程,它會(huì)直接進(jìn)入 Blocked 狀態(tài)。這是為什么?
其他線程能調(diào)用 notify () 或 notifyAll () 試圖喚醒 Waiting 狀態(tài)線程,說明必須持有同一個(gè) monitor 鎖,也就是說處于 Waiting 的線程被喚醒后并不能馬上搶到 monitor 鎖,所以它必須先進(jìn)入 Blocked 狀態(tài)。而喚醒它的線程執(zhí)行完畢釋放鎖后,它能搶到鎖就從 Blocked 進(jìn)入 Runnable 狀態(tài)。
這種狀態(tài)與 Waiting 狀態(tài)的區(qū)別在于:有沒有時(shí)間限制,Timed Waiting 會(huì)等待超時(shí),由系統(tǒng)自動(dòng)喚醒,或者在超時(shí)前被喚醒信號(hào)喚醒。
有以下 5 種情況會(huì)讓線程進(jìn)入 Timed Waiting 狀態(tài):
設(shè)置 Timeout 參數(shù)的 Thread.sleep (time) 方法。
設(shè)置 Timeout 參數(shù)的 Object.wait (time) 方法。
設(shè)置 Timeout 參數(shù)的 Thread.join (time) 方法。
設(shè)置 Timeout 參數(shù)的 LockSupport.parkNanos (long nanos) 方法。
設(shè)置 Timeout 參數(shù)的 LockSupport.parkUntil (long deadline) 方法。
線程的 6 種狀態(tài)
看 Timed Waiting 右側(cè),Timed Waiting ----> Blocked:跟 Waiting 一樣,其他線程執(zhí)行 notify () 和 notifyAll (),當(dāng)前線程也是先進(jìn)入 Blocked 狀態(tài),而后視鎖的獲取情況再?zèng)Q定是否進(jìn)入 Runnable 狀態(tài)。
另外,Timed Waiting ----> Runnable :1、當(dāng)前線程的超時(shí)時(shí)間到了且能直接獲取到鎖,2、join 的線程運(yùn)行結(jié)束,3、被中斷,4、調(diào)用了 LockSupport.unpark (),這幾種情況會(huì)直接恢復(fù)到 Runnable,而無需經(jīng)歷 Blocked 狀態(tài)。
最后一種,想要進(jìn)入終止?fàn)顟B(tài)就比較簡(jiǎn)單了,有三種情況:
任務(wù)執(zhí)行完畢,線程正常退出。
出現(xiàn)一個(gè)沒有捕獲的異常(比如直接調(diào)用 interrupt () 方法)。
到此,關(guān)于“java線程有多少種狀態(tài)”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。