南江縣建設(shè)局網(wǎng)站企業(yè)線上培訓(xùn)平臺(tái)有哪些
線程的六種狀態(tài)
- (1) NEW(初始狀態(tài))
- (2) TERMINATED(終止?fàn)顟B(tài) / 死亡狀態(tài))
- (3) RUNNABLE(運(yùn)行時(shí)狀態(tài))
- (4) TIMED_WAITING(超時(shí)等待狀態(tài))
- (5) WAITING(等待狀態(tài))
- (6) BLOCK(阻塞狀態(tài))
- sleep和wait的區(qū)別:
操作系統(tǒng)里的線程自身是有一個(gè)狀態(tài)的,但是java Thread 是對(duì)系統(tǒng)線程的封裝,把這里的狀態(tài)又進(jìn)一步細(xì)化了~~
狀態(tài) | 說(shuō)明 |
---|---|
NEW | 線程還沒(méi)有創(chuàng)建,但是線程對(duì)象已經(jīng)創(chuàng)建出來(lái)了 |
TERMINATED | 線程結(jié)束了,但是線程對(duì)象還存在 |
RUNNABLE | 就緒狀態(tài),可以細(xì)分為兩個(gè)狀態(tài) |
TIMED_WAITING | 指超時(shí)等待狀態(tài) |
BLOCK | 等待狀態(tài) |
WAITING | 表示阻塞時(shí)出現(xiàn)的狀態(tài) |
下面將通過(guò)代碼運(yùn)行結(jié)果來(lái)帶大家細(xì)致了解線程運(yùn)行的狀態(tài).
(1) NEW(初始狀態(tài))
public static void main(String[] args) {Thread t = new Thread(()->{System.out.println("t 線程");});//獲取線程的狀態(tài)System.out.println("當(dāng)前線程是 " +t.getState() + "狀態(tài)");//調(diào)用start(),創(chuàng)建這個(gè)線程t.start();}
NEW狀態(tài)指的是 : 線程在剛剛被new出來(lái)的時(shí)候,還沒(méi)有調(diào)用start()的狀態(tài).
此時(shí)可以稱這個(gè)狀態(tài)為: (1) 初始狀態(tài) (2) 創(chuàng)建狀態(tài)
運(yùn)行結(jié)果:
(2) TERMINATED(終止?fàn)顟B(tài) / 死亡狀態(tài))
public static void main(String[] args) {Thread t = new Thread(()->{System.out.println("t 線程");});//調(diào)用start(),創(chuàng)建這個(gè)線程t.start();try {//由于計(jì)算機(jī)的執(zhí)行速度是很快的,所以1000ms足夠t線程執(zhí)行完Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}//獲取線程的狀態(tài)System.out.println("當(dāng)前線程是 " +t.getState() + "狀態(tài)");t.start();}
如果一個(gè)線程的 run()
方法執(zhí)行結(jié)束 該線程就會(huì)死亡,對(duì)于已經(jīng)死亡的線程,無(wú)法再使用 start()
方法令其進(jìn)入就緒.
運(yùn)行結(jié)果:
(3) RUNNABLE(運(yùn)行時(shí)狀態(tài))
運(yùn)行時(shí)狀態(tài)可以細(xì)分為兩個(gè)狀態(tài):(1) 正在運(yùn)行狀態(tài)RUNNING
(2) 就緒狀態(tài)READY
我們可以這么理解 :
(1) 例如我女朋友下班了,我正在帶我女朋友去吃飯,此時(shí)就是正在運(yùn)行狀態(tài).
(2)因?yàn)槲姨崆跋掳嗔?但是我女朋友還沒(méi)有下班,所以此時(shí)我在女朋友公司門口等她,只要她下班我隨時(shí)可以帶她吃飯去,此時(shí)我就是就緒狀態(tài).
通過(guò)代碼實(shí)現(xiàn)(1) :
public static void main(String[] args) {Thread t = new Thread(()->{while(true){//什么都不打印,防止把下面的打印信息沖走}});//調(diào)用start(),創(chuàng)建這個(gè)線程t.start();//運(yùn)行線程時(shí)判斷此時(shí)的狀態(tài)System.out.println("當(dāng)先線程是 "+t.getState()+"狀態(tài)");}
由于此時(shí)的 t 線程一直在執(zhí)行死循環(huán),所以 t 線程的狀態(tài)是正在運(yùn)行的~~
運(yùn)行結(jié)果:
(4) TIMED_WAITING(超時(shí)等待狀態(tài))
可以理解為,具有指定等待時(shí)間的,正在等待(阻塞)線程的線程狀態(tài),由于調(diào)用具有指定等待時(shí)間的以下方法之一,線程處于定時(shí)等待狀態(tài).
具有指定等待時(shí)間的方法:
(1) Thread.sleep(參數(shù))指定時(shí)間,單位為ms
該方法會(huì)讓當(dāng)前線程暫停一段時(shí)間,其他線程有機(jī)會(huì)獲得 CPU 時(shí)間片。
(2) t.join(參數(shù))
調(diào)用 t.join
的線程需要等待線程 t 執(zhí)行指定時(shí)間后,才可以運(yùn)行,等待的過(guò)程中是處于阻塞狀態(tài)的.
(3) wait(參數(shù)) :wait 方法提供一個(gè)帶有 timeout 參數(shù)的版本, 來(lái)指定等待時(shí)間.超過(guò)這個(gè)時(shí)間之后無(wú)需其他線程調(diào)用該對(duì)象的 notify()
或 notifyAll()
方法喚醒該線程,該線程自己就會(huì)喚醒.
代碼實(shí)現(xiàn)(1)
public static void main(String[] args) {Thread t = new Thread(()->{try {//睡眠1000msThread.sleep(1000);System.out.println("hello t");} catch (InterruptedException e) {e.printStackTrace();}});//調(diào)用start(),創(chuàng)建這個(gè)線程t.start();try {//等待1000ms,此時(shí)t線程就創(chuàng)建結(jié)束,系統(tǒng)自動(dòng)執(zhí)行run方法里面的邏輯Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}//運(yùn)行線程時(shí)判斷此時(shí)的狀態(tài)System.out.println("當(dāng)先線程是 "+t.getState()+"狀態(tài)");}
運(yùn)行結(jié)果:
代碼實(shí)現(xiàn)(2)
public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(()->{while (true){try {//每500ms打印一次Thread.sleep(500);System.out.println("t1");} catch (InterruptedException e) {e.printStackTrace();}}});Thread t2 = new Thread(()->{try {//等待t1線程執(zhí)行完1000ms//t2線程再開(kāi)始執(zhí)行t1.join(1000);System.out.println("t2");} catch (InterruptedException e) {e.printStackTrace();}});//創(chuàng)建t1線程t1.start();//創(chuàng)建t2線程t2.start();//等待500ms此時(shí)兩個(gè)線程都創(chuàng)建完畢Thread.sleep(500);System.out.println("當(dāng)先線程是 "+t2.getState()+"狀態(tài)");}
運(yùn)行結(jié)果:
代碼實(shí)現(xiàn)(3)
public class ThreadDemo8 {//自己指定的鎖對(duì)象static Object object = new Object();public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(()->{//兩個(gè)鎖對(duì)象相同synchronized (object){for (int i = 0; i < 10; i++) {if(i == 5) {try {object.wait(1000);//雖然過(guò)了1000ms,但是還是需要等待t2線程中鎖里面的程序執(zhí)行完// 才可以繼續(xù)執(zhí)行鎖.(這里是指,僅有兩個(gè)鎖,且鎖對(duì)象相等的情況)} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(i);}}});Thread t2 = new Thread(()->{//兩個(gè)鎖對(duì)象相同synchronized (object){for (int i = 0; i <10 ; i++) {try {System.out.println("t2");Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}}}});//t1線程先創(chuàng)建t1.start();//等待100ms是防止t2先搶到鎖Thread.sleep(100);//創(chuàng)建t2線程t2.start();//查看當(dāng)前線程的狀態(tài)System.out.println("當(dāng)先線程是 "+t1.getState()+"狀態(tài)");}
}
運(yùn)行結(jié)果:
(5) WAITING(等待狀態(tài))
處于這種狀態(tài)的線程不會(huì)被CPU分配執(zhí)行時(shí)間,他們要等待的顯示被喚醒,否則會(huì)處于無(wú)限期的等待狀態(tài)
具有阻塞的方法:
(1)使用 Thread.join()
方法。該方法會(huì)讓當(dāng)前線程等待另一個(gè)線程終止
(2) 使用 Object.wait()
方法。該方法會(huì)讓當(dāng)前線程等待,直到其他線程調(diào)用該對(duì)象的 notify() 或 notifyAll() 方法喚醒該線程。
我們這里只演示第一種就好~
public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(()->{while (true){}});Thread t2 = new Thread(()->{try {t1.join();} catch (InterruptedException e) {e.printStackTrace();}},"豬豬俠");//創(chuàng)建這t1線程t1.start();//等待200ms讓t1線程優(yōu)先創(chuàng)建好Thread.sleep(200);//創(chuàng)建這t2線程t2.start();//等待200ms讓t2線程優(yōu)先創(chuàng)建好Thread.sleep(200);System.out.println("當(dāng)先線程 "+t2.getName()+"的狀態(tài)是"+t2.getState()+"狀態(tài)");}
運(yùn)行結(jié)果是:
(6) BLOCK(阻塞狀態(tài))
阻塞狀態(tài)(Blocked):阻塞狀態(tài)是線程因?yàn)槟撤N原因放棄cpu的使用權(quán),暫?;蛲V惯\(yùn)行,直到線程進(jìn)入就緒狀態(tài),才有機(jī)會(huì)獲得cpu的青睞從而轉(zhuǎn)入運(yùn)行狀態(tài)。
我們可以通俗點(diǎn)理解為~ 等待鎖的狀態(tài).
例如: t1 和 t2 需要的鎖對(duì)象相同,如果此時(shí) t1 拿到了鎖,當(dāng) t2 執(zhí)行到進(jìn)入鎖的代碼的時(shí)候, t2 就需要等 t1 釋放鎖之后才可以拿到這把鎖.
我們通過(guò)代碼演示:
public class ThreadDemo8 {static Object object = new Object();public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(()->{//兩個(gè)鎖對(duì)象相同synchronized (object){while (true){}}});Thread t2 = new Thread(()->{//兩個(gè)鎖對(duì)象相同//由于先執(zhí)行的t1所以需要等t1釋放鎖才可以執(zhí)行t2//此時(shí)t2處于阻塞狀態(tài)synchronized (object){System.out.println("t2");}},"豬豬俠");//創(chuàng)建這t1線程t1.start();//等待200ms讓t1線程優(yōu)先創(chuàng)建好Thread.sleep(200);//創(chuàng)建這t2線程t2.start();//等待200ms讓t2線程優(yōu)先創(chuàng)建好Thread.sleep(200);//查看t2線程的狀態(tài)System.out.println("當(dāng)先線程 "+t2.getName()+"的狀態(tài)是"+t2.getState()+"狀態(tài)");}
}
運(yùn)行結(jié)果:
關(guān)于線程狀態(tài)的關(guān)系圖:
sleep和wait的區(qū)別:
sleep()和wait()方法有什么區(qū)別:
sleep()睡眠時(shí),保持對(duì)象鎖,仍然占有該鎖;
而wait()睡眠時(shí),釋放對(duì)象鎖。
但是wait()和sleep()都可以通過(guò)interrupt()方法打斷線程的暫停狀態(tài),從而使線程立刻拋出InterruptedException(但不建議使用該方法)。