JAVA多線程之線程的生命周期

來源: https://www.cnblogs.com/albertrui/p/8383799.html

一、前言

  當(dāng)線程被創(chuàng)建并啟動(dòng)以后庵寞,它既不是一啟動(dòng)就進(jìn)入了執(zhí)行狀態(tài)共啃,也不是一直處于執(zhí)行狀態(tài)。在線程的生命周期中返帕,它要經(jīng)過新建(New)夫嗓、就緒(Runnable)迟螺、運(yùn)行(Running)、阻塞(Blocked)和死亡(Dead)5種狀態(tài)舍咖。尤其是當(dāng)線程啟動(dòng)以后矩父,它不可能一直"霸占"著CPU獨(dú)自運(yùn)行,所以CPU需要在多條線程之間切換排霉,于是線程狀態(tài)也會(huì)多次在運(yùn)行窍株、阻塞之間切換

新建狀態(tài),當(dāng)程序使用new關(guān)鍵字創(chuàng)建了一個(gè)線程之后攻柠,該線程就處于新建狀態(tài)扫责,此時(shí)僅由JVM為其分配內(nèi)存曾沈,并初始化其成員變量的值

就緒狀態(tài)司致,當(dāng)線程對(duì)象調(diào)用了start()方法之后量淌,該線程處于就緒狀態(tài)轻抱。Java虛擬機(jī)會(huì)為其創(chuàng)建方法調(diào)用棧和程序計(jì)數(shù)器飞涂,等待調(diào)度運(yùn)行

運(yùn)行狀態(tài),如果處于就緒狀態(tài)的線程獲得了CPU,開始執(zhí)行run()方法的線程執(zhí)行體较店,則該線程處于運(yùn)行狀態(tài)

阻塞狀態(tài)士八,當(dāng)處于運(yùn)行狀態(tài)的線程失去所占用資源之后,便進(jìn)入阻塞狀態(tài)

死亡狀態(tài)梁呈,線程在run()方法執(zhí)行結(jié)束后進(jìn)入死亡狀態(tài)婚度。此外,如果線程執(zhí)行了interrupt()或stop()方法官卡,那么它也會(huì)以異常退出的方式進(jìn)入死亡狀態(tài)蝗茁。

二、新建和就緒狀態(tài)

  當(dāng)程序使用new關(guān)鍵字創(chuàng)建了一個(gè)線程之后寻咒,該線程就處于新建狀態(tài)哮翘,此時(shí)它和其他的Java對(duì)象一樣,僅僅由Java虛擬機(jī)為其分配內(nèi)存毛秘,并初始化其成員變量的值饭寺。此時(shí)的線程對(duì)象沒有表現(xiàn)出任何線程的動(dòng)態(tài)特征,程序也不會(huì)執(zhí)行線程的線程執(zhí)行體叫挟。

  當(dāng)線程對(duì)象調(diào)用了start()方法之后艰匙,該線程處于就緒狀態(tài)。Java虛擬機(jī)會(huì)為其創(chuàng)建方法調(diào)用棧和程序計(jì)數(shù)器抹恳,處于這個(gè)狀態(tài)中的線程并沒有開始運(yùn)行员凝,只是表示該線程可以運(yùn)行了。至于該線程何時(shí)開始運(yùn)行奋献,取決于JVM里線程調(diào)度器的調(diào)度绊序。

注意:?jiǎn)?dòng)線程使用start()方法,而不是run()方法秽荞。永遠(yuǎn)不要調(diào)用線程對(duì)象的run()方法骤公。調(diào)用start0方法來啟動(dòng)線程,系統(tǒng)會(huì)把該run()方法當(dāng)成線程執(zhí)行體來處理扬跋;但如果直按調(diào)用線程對(duì)象的run()方法阶捆,則run()方法立即就會(huì)被執(zhí)行,而且在run()方法返回之前其他線程無法并發(fā)執(zhí)行钦听。也就是說洒试,系統(tǒng)把線程對(duì)象當(dāng)成一個(gè)普通對(duì)象,而run()方法也是一個(gè)普通方法朴上,而不是線程執(zhí)行體垒棋。需要指出的是,調(diào)用了線程的run()方法之后痪宰,該線程已經(jīng)不再處于新建狀態(tài)叼架,不要再次調(diào)用線程對(duì)象的start()方法畔裕。只能對(duì)處于新建狀態(tài)的線程調(diào)用start()方法,否則將引發(fā)IllegaIThreadStateExccption異常乖订。

  調(diào)用線程對(duì)象的start()方法之后扮饶,該線程立即進(jìn)入就緒狀態(tài)——就緒狀態(tài)相當(dāng)于"等待執(zhí)行",但該線程并未真正進(jìn)入運(yùn)行狀態(tài)乍构。如果希望調(diào)用子線程的start()方法后子線程立即開始執(zhí)行甜无,程序可以使用Thread.sleep(1) 來讓當(dāng)前運(yùn)行的線程(主線程)睡眠1毫秒,1毫秒就夠了哥遮,因?yàn)樵谶@1毫秒內(nèi)CPU不會(huì)空閑岂丘,它會(huì)去執(zhí)行另一個(gè)處于就緒狀態(tài)的線程,這樣就可以讓子線程立即開始執(zhí)行眠饮。

三元潘、運(yùn)行和阻塞狀態(tài)

3.1 線程調(diào)度

  如果處于就緒狀態(tài)的線程獲得了CPU,開始執(zhí)行run()方法的線程執(zhí)行體君仆,則該線程處于運(yùn)行狀態(tài)翩概,如果計(jì)算機(jī)只有一個(gè)CPU。那么在任何時(shí)刻只有一個(gè)線程處于運(yùn)行狀態(tài)返咱,當(dāng)然在一個(gè)多處理器的機(jī)器上钥庇,將會(huì)有多個(gè)線程并行執(zhí)行;當(dāng)線程數(shù)大于處理器數(shù)時(shí)咖摹,依然會(huì)存在多個(gè)線程在同一個(gè)CPU上輪換的現(xiàn)象评姨。

  當(dāng)一個(gè)線程開始運(yùn)行后,它不可能一直處于運(yùn)行狀態(tài)(除非它的線程執(zhí)行體足夠短萤晴,瞬間就執(zhí)行結(jié)束了)吐句。線程在運(yùn)行過程中需要被中斷,目的是使其他線程獲得執(zhí)行的機(jī)會(huì)店读,線程調(diào)度的細(xì)節(jié)取決于底層平臺(tái)所采用的策略嗦枢。對(duì)于采用搶占式策略的系統(tǒng)而言,系統(tǒng)會(huì)給每個(gè)可執(zhí)行的線程一個(gè)小時(shí)間段來處理任務(wù)屯断;當(dāng)該時(shí)間段用完后文虏,系統(tǒng)就會(huì)剝奪該線程所占用的資源,讓其他線程獲得執(zhí)行的機(jī)會(huì)殖演。在選擇下一個(gè)線程時(shí)氧秘,系統(tǒng)會(huì)考慮線程的優(yōu)先級(jí)。

  所有現(xiàn)代的桌面和服務(wù)器操作系統(tǒng)都采用搶占式調(diào)度策略趴久,但一些小型設(shè)備如手機(jī)則可能采用協(xié)作式調(diào)度策略丸相,在這樣的系統(tǒng)中,只有當(dāng)一個(gè)線程調(diào)用了它的sleep()或yield()方法后才會(huì)放棄所占用的資源——也就是必須由該線程主動(dòng)放棄所占用的資源彼棍。

3.2 線程阻塞

  當(dāng)發(fā)生如下情況時(shí)灭忠,線程將會(huì)進(jìn)入阻塞狀態(tài)

 ∩潘恪① 線程調(diào)用sleep()方法主動(dòng)放棄所占用的處理器資源

  ② 線程調(diào)用了一個(gè)阻塞式IO方法更舞,在該方法返回之前,該線程被阻塞

 】参恰③ 線程試圖獲得一個(gè)同步監(jiān)視器缆蝉,但該同步監(jiān)視器正被其他線程所持有。關(guān)于同步監(jiān)視器的知識(shí)瘦真、后面將有深入的介紹

 】贰④ 線程在等待某個(gè)通知(notify)

  ⑤ 程序調(diào)用了線程的suspend()方法將該線程掛起诸尽。但這個(gè)方法容易導(dǎo)致死鎖原杂,所以應(yīng)該盡量避免使用該方法

  當(dāng)前正在執(zhí)行的線程被阻塞之后,其他線程就可以獲得執(zhí)行的機(jī)會(huì)您机。被阻塞的線程會(huì)在合適的時(shí)候重新進(jìn)入就緒狀態(tài)穿肄,注意是就緒狀態(tài)而不是運(yùn)行狀態(tài)。也就是說际看,被阻塞線程的阻塞解除后咸产,必須重新等待線程調(diào)度器再次調(diào)度它。

2.3 解除阻塞

  針對(duì)上面幾種情況仲闽,當(dāng)發(fā)生如下特定的情況時(shí)可以解除上面的阻塞脑溢,讓該線程重新進(jìn)入就緒狀態(tài):

  ① 調(diào)用sleep()方法的線程經(jīng)過了指定時(shí)間赖欣。

 ⌒汲埂② 線程調(diào)用的阻塞式IO方法已經(jīng)返回。

 《ニ薄③ 線程成功地獲得了試圖取得的同步監(jiān)視器社牲。

  ④ 線程正在等待某個(gè)通知時(shí)悴了,其他線程發(fā)出了個(gè)通知膳沽。

  ⑤ 處于掛起狀態(tài)的線程被調(diào)甩了resdme()恢復(fù)方法让禀。

  圖 3.1 線程狀態(tài)轉(zhuǎn)換圖

  從圖3.1中可以看出挑社,線程從阻塞狀態(tài)只能進(jìn)入就緒狀態(tài),無法直接進(jìn)入運(yùn)行狀態(tài)巡揍。而就緒和運(yùn)行狀態(tài)之間的轉(zhuǎn)換通常不受程序控制痛阻,而是由系統(tǒng)線程調(diào)度所決定。當(dāng)處于就緒狀態(tài)的線程獲得處理器資源時(shí)腮敌,該線程進(jìn)入運(yùn)行狀態(tài)阱当;當(dāng)處于運(yùn)行狀態(tài)的線程失去處理器資源時(shí)俏扩,該線程進(jìn)入就緒狀態(tài)。但有一個(gè)方法例外弊添,調(diào)用yield()方法可以讓運(yùn)行狀態(tài)的線程轉(zhuǎn)入就緒狀態(tài)录淡。關(guān)于yield()方法后面有更詳細(xì)的介紐。

四油坝、線程死亡

4.1 死亡狀態(tài)

  線程會(huì)以如下3種方式結(jié)束嫉戚,結(jié)束后就處于死亡狀態(tài):

  ① run()或call()方法執(zhí)行完成澈圈,線程正常結(jié)束彬檀。

  ② 線程拋出一個(gè)未捕獲的Exception或Error瞬女。

 ∏系邸③ 直接調(diào)用該線程stop()方法來結(jié)束該線程——該方法容易導(dǎo)致死鎖,通常不推薦使用诽偷。

4.2 程序設(shè)計(jì)

  當(dāng)主線程結(jié)束時(shí)坤学,其他線程不受任何影響,并不會(huì)隨之結(jié)束报慕。一旦子線程啟動(dòng)起來后拥峦,它就擁有和主線程相同的地位,它不會(huì)受主線程的影響卖子。為了測(cè)試某個(gè)線程是否已經(jīng)死亡略号,可以調(diào)用線程對(duì)象的isAlivc()方法,當(dāng)線程處于就緒洋闽、運(yùn)行玄柠、阻塞了種狀態(tài)時(shí),該方法將返回true诫舅;當(dāng)線程處于新建羽利、死亡狀態(tài)時(shí),該方法將返回false刊懈。

切記这弧,不要試圖對(duì)一個(gè)已經(jīng)死亡的線程調(diào)用start()方法使它重新啟動(dòng),死亡就是死亡虚汛,該線程將不可再次作為線程執(zhí)行匾浪。

下面程序嘗試對(duì)處于死亡狀態(tài)的線程再次調(diào)用start()。

package test;

public class StartDead extends Thread {

???private int i;


???// 重寫run方法卷哩,run方法的方法體就是線程執(zhí)行體

???public void run() {

??????for (; i < 100; i++) {

?????????System.out.println(getName() + "" + i);

??????}

???}


???public static void main(String[] args) {

??????// 創(chuàng)建線程對(duì)象

??????StartDead sd = new StartDead();

??????for (int i = 0; i < 300; i++) {

?????????// 調(diào)用Thread的currentThread方法獲取當(dāng)前線程

?????????System.out.println(Thread.currentThread().getName() + "" + i);

?????????if (i == 20) {

????????????// 啟動(dòng)線程

????????????sd.start();

????????????// 判斷啟動(dòng)后線程的isAlive()值蛋辈,輸出true

????????????System.out.println(sd.isAlive());

?????????}

?????????// 只有當(dāng)線程處于新建、死亡兩種狀態(tài)時(shí)isAlive()方法返回false。

?????????// 當(dāng)i > 20冷溶,則該線程肯定已經(jīng)啟動(dòng)過了渐白,如果sd.isAlive()為假時(shí),

?????????// 那只能是死亡狀態(tài)了逞频。

?????????if (i > 20 && !sd.isAlive())


?????????{

????????????// 試圖再次啟動(dòng)該線程

?sd.start();

?????????}

??????}

???}

}

4.3 運(yùn)行結(jié)果

main 0

main 1

main 2

main 3

main 4

main 5

main 6

main 7

main 8

main 9

main 10

main 11

main 12

main 13

main 14

main 15

main 16

main 17

main 18

main 19

main 20

true

main 21

…………

Thread-0 0

Thread-0 1

Thread-0 2

Thread-0 3

Thread-0 4

Thread-0 5

Thread-0 6

Thread-0 7

Thread-0 8

………………

Thread-0 92

Thread-0 93

Thread-0 94

Thread-0 95

Thread-0 96

Thread-0 97

Thread-0 98

Thread-0 99

main 25

Exception


main→主線程

Thread-0→線程1

Exception→異常

  上面程序中的粗體字代碼試圖在線程已死亡的情況下再次調(diào)用start()方法來啟動(dòng)該線程纯衍。運(yùn)行上面程序,將引發(fā)IllegaIThreadStateException異常苗胀,這表明處于死亡狀態(tài)的線程無法再次運(yùn)行了襟诸。一、前言

  當(dāng)線程被創(chuàng)建并啟動(dòng)以后柒巫,它既不是一啟動(dòng)就進(jìn)入了執(zhí)行狀態(tài)励堡,也不是一直處于執(zhí)行狀態(tài)谷丸。在線程的生命周期中堡掏,它要經(jīng)過新建(New)、就緒(Runnable)刨疼、運(yùn)行(Running)泉唁、阻塞(Blocked)和死亡(Dead)5種狀態(tài)。尤其是當(dāng)線程啟動(dòng)以后揩慕,它不可能一直"霸占"著CPU獨(dú)自運(yùn)行亭畜,所以CPU需要在多條線程之間切換,于是線程狀態(tài)也會(huì)多次在運(yùn)行迎卤、阻塞之間切換

新建狀態(tài)拴鸵,當(dāng)程序使用new關(guān)鍵字創(chuàng)建了一個(gè)線程之后,該線程就處于新建狀態(tài)蜗搔,此時(shí)僅由JVM為其分配內(nèi)存劲藐,并初始化其成員變量的值

就緒狀態(tài),當(dāng)線程對(duì)象調(diào)用了start()方法之后樟凄,該線程處于就緒狀態(tài)聘芜。Java虛擬機(jī)會(huì)為其創(chuàng)建方法調(diào)用棧和程序計(jì)數(shù)器,等待調(diào)度運(yùn)行

運(yùn)行狀態(tài)缝龄,如果處于就緒狀態(tài)的線程獲得了CPU汰现,開始執(zhí)行run()方法的線程執(zhí)行體,則該線程處于運(yùn)行狀態(tài)

阻塞狀態(tài)叔壤,當(dāng)處于運(yùn)行狀態(tài)的線程失去所占用資源之后瞎饲,便進(jìn)入阻塞狀態(tài)

死亡狀態(tài),線程在run()方法執(zhí)行結(jié)束后進(jìn)入死亡狀態(tài)炼绘。此外企软,如果線程執(zhí)行了interrupt()或stop()方法,那么它也會(huì)以異常退出的方式進(jìn)入死亡狀態(tài)饭望。

二仗哨、新建和就緒狀態(tài)

  當(dāng)程序使用new關(guān)鍵字創(chuàng)建了一個(gè)線程之后形庭,該線程就處于新建狀態(tài),此時(shí)它和其他的Java對(duì)象一樣厌漂,僅僅由Java虛擬機(jī)為其分配內(nèi)存萨醒,并初始化其成員變量的值。此時(shí)的線程對(duì)象沒有表現(xiàn)出任何線程的動(dòng)態(tài)特征苇倡,程序也不會(huì)執(zhí)行線程的線程執(zhí)行體富纸。

  當(dāng)線程對(duì)象調(diào)用了start()方法之后,該線程處于就緒狀態(tài)旨椒。Java虛擬機(jī)會(huì)為其創(chuàng)建方法調(diào)用棧和程序計(jì)數(shù)器晓褪,處于這個(gè)狀態(tài)中的線程并沒有開始運(yùn)行,只是表示該線程可以運(yùn)行了综慎。至于該線程何時(shí)開始運(yùn)行涣仿,取決于JVM里線程調(diào)度器的調(diào)度。

注意:?jiǎn)?dòng)線程使用start()方法示惊,而不是run()方法好港。永遠(yuǎn)不要調(diào)用線程對(duì)象的run()方法。調(diào)用start0方法來啟動(dòng)線程米罚,系統(tǒng)會(huì)把該run()方法當(dāng)成線程執(zhí)行體來處理钧汹;但如果直按調(diào)用線程對(duì)象的run()方法,則run()方法立即就會(huì)被執(zhí)行录择,而且在run()方法返回之前其他線程無法并發(fā)執(zhí)行拔莱。也就是說,系統(tǒng)把線程對(duì)象當(dāng)成一個(gè)普通對(duì)象隘竭,而run()方法也是一個(gè)普通方法塘秦,而不是線程執(zhí)行體。需要指出的是货裹,調(diào)用了線程的run()方法之后嗤形,該線程已經(jīng)不再處于新建狀態(tài),不要再次調(diào)用線程對(duì)象的start()方法弧圆。只能對(duì)處于新建狀態(tài)的線程調(diào)用start()方法赋兵,否則將引發(fā)IllegaIThreadStateExccption異常。

  調(diào)用線程對(duì)象的start()方法之后搔预,該線程立即進(jìn)入就緒狀態(tài)——就緒狀態(tài)相當(dāng)于"等待執(zhí)行"霹期,但該線程并未真正進(jìn)入運(yùn)行狀態(tài)。如果希望調(diào)用子線程的start()方法后子線程立即開始執(zhí)行拯田,程序可以使用Thread.sleep(1) 來讓當(dāng)前運(yùn)行的線程(主線程)睡眠1毫秒历造,1毫秒就夠了,因?yàn)樵谶@1毫秒內(nèi)CPU不會(huì)空閑,它會(huì)去執(zhí)行另一個(gè)處于就緒狀態(tài)的線程吭产,這樣就可以讓子線程立即開始執(zhí)行侣监。

三、運(yùn)行和阻塞狀態(tài)

3.1 線程調(diào)度

  如果處于就緒狀態(tài)的線程獲得了CPU臣淤,開始執(zhí)行run()方法的線程執(zhí)行體橄霉,則該線程處于運(yùn)行狀態(tài),如果計(jì)算機(jī)只有一個(gè)CPU邑蒋。那么在任何時(shí)刻只有一個(gè)線程處于運(yùn)行狀態(tài)姓蜂,當(dāng)然在一個(gè)多處理器的機(jī)器上,將會(huì)有多個(gè)線程并行執(zhí)行医吊;當(dāng)線程數(shù)大于處理器數(shù)時(shí)钱慢,依然會(huì)存在多個(gè)線程在同一個(gè)CPU上輪換的現(xiàn)象。

  當(dāng)一個(gè)線程開始運(yùn)行后卿堂,它不可能一直處于運(yùn)行狀態(tài)(除非它的線程執(zhí)行體足夠短束莫,瞬間就執(zhí)行結(jié)束了)。線程在運(yùn)行過程中需要被中斷御吞,目的是使其他線程獲得執(zhí)行的機(jī)會(huì)麦箍,線程調(diào)度的細(xì)節(jié)取決于底層平臺(tái)所采用的策略漓藕。對(duì)于采用搶占式策略的系統(tǒng)而言陶珠,系統(tǒng)會(huì)給每個(gè)可執(zhí)行的線程一個(gè)小時(shí)間段來處理任務(wù);當(dāng)該時(shí)間段用完后享钞,系統(tǒng)就會(huì)剝奪該線程所占用的資源揍诽,讓其他線程獲得執(zhí)行的機(jī)會(huì)。在選擇下一個(gè)線程時(shí)栗竖,系統(tǒng)會(huì)考慮線程的優(yōu)先級(jí)暑脆。

  所有現(xiàn)代的桌面和服務(wù)器操作系統(tǒng)都采用搶占式調(diào)度策略,但一些小型設(shè)備如手機(jī)則可能采用協(xié)作式調(diào)度策略狐肢,在這樣的系統(tǒng)中添吗,只有當(dāng)一個(gè)線程調(diào)用了它的sleep()或yield()方法后才會(huì)放棄所占用的資源——也就是必須由該線程主動(dòng)放棄所占用的資源。

3.2 線程阻塞

  當(dāng)發(fā)生如下情況時(shí)份名,線程將會(huì)進(jìn)入阻塞狀態(tài)

 〉① 線程調(diào)用sleep()方法主動(dòng)放棄所占用的處理器資源

  ② 線程調(diào)用了一個(gè)阻塞式IO方法僵腺,在該方法返回之前鲤孵,該線程被阻塞

  ③ 線程試圖獲得一個(gè)同步監(jiān)視器辰如,但該同步監(jiān)視器正被其他線程所持有普监。關(guān)于同步監(jiān)視器的知識(shí)、后面將有深入的介紹

  ④ 線程在等待某個(gè)通知(notify)

 】⑤ 程序調(diào)用了線程的suspend()方法將該線程掛起毙玻。但這個(gè)方法容易導(dǎo)致死鎖,所以應(yīng)該盡量避免使用該方法

  當(dāng)前正在執(zhí)行的線程被阻塞之后廊散,其他線程就可以獲得執(zhí)行的機(jī)會(huì)淆珊。被阻塞的線程會(huì)在合適的時(shí)候重新進(jìn)入就緒狀態(tài),注意是就緒狀態(tài)而不是運(yùn)行狀態(tài)奸汇。也就是說施符,被阻塞線程的阻塞解除后,必須重新等待線程調(diào)度器再次調(diào)度它擂找。

2.3 解除阻塞

  針對(duì)上面幾種情況戳吝,當(dāng)發(fā)生如下特定的情況時(shí)可以解除上面的阻塞,讓該線程重新進(jìn)入就緒狀態(tài):

 」嵯选① 調(diào)用sleep()方法的線程經(jīng)過了指定時(shí)間听哭。

  ② 線程調(diào)用的阻塞式IO方法已經(jīng)返回塘雳。

 ÷脚獭③ 線程成功地獲得了試圖取得的同步監(jiān)視器。

 “苊鳌④ 線程正在等待某個(gè)通知時(shí)隘马,其他線程發(fā)出了個(gè)通知。

 ∑薅ァ⑤ 處于掛起狀態(tài)的線程被調(diào)甩了resdme()恢復(fù)方法酸员。

  圖 3.1 線程狀態(tài)轉(zhuǎn)換圖


  從圖3.1中可以看出,線程從阻塞狀態(tài)只能進(jìn)入就緒狀態(tài)讳嘱,無法直接進(jìn)入運(yùn)行狀態(tài)幔嗦。而就緒和運(yùn)行狀態(tài)之間的轉(zhuǎn)換通常不受程序控制,而是由系統(tǒng)線程調(diào)度所決定沥潭。當(dāng)處于就緒狀態(tài)的線程獲得處理器資源時(shí)邀泉,該線程進(jìn)入運(yùn)行狀態(tài);當(dāng)處于運(yùn)行狀態(tài)的線程失去處理器資源時(shí)钝鸽,該線程進(jìn)入就緒狀態(tài)汇恤。但有一個(gè)方法例外,調(diào)用yield()方法可以讓運(yùn)行狀態(tài)的線程轉(zhuǎn)入就緒狀態(tài)寞埠。關(guān)于yield()方法后面有更詳細(xì)的介紐屁置。

四、線程死亡

4.1 死亡狀態(tài)

  線程會(huì)以如下3種方式結(jié)束仁连,結(jié)束后就處于死亡狀態(tài):

 ±督恰① run()或call()方法執(zhí)行完成阱穗,線程正常結(jié)束。

 ∈苟臁② 線程拋出一個(gè)未捕獲的Exception或Error揪阶。

  ③ 直接調(diào)用該線程stop()方法來結(jié)束該線程——該方法容易導(dǎo)致死鎖患朱,通常不推薦使用鲁僚。

4.2 程序設(shè)計(jì)

  當(dāng)主線程結(jié)束時(shí),其他線程不受任何影響裁厅,并不會(huì)隨之結(jié)束冰沙。一旦子線程啟動(dòng)起來后,它就擁有和主線程相同的地位执虹,它不會(huì)受主線程的影響拓挥。為了測(cè)試某個(gè)線程是否已經(jīng)死亡,可以調(diào)用線程對(duì)象的isAlivc()方法袋励,當(dāng)線程處于就緒侥啤、運(yùn)行、阻塞了種狀態(tài)時(shí)茬故,該方法將返回true盖灸;當(dāng)線程處于新建、死亡狀態(tài)時(shí)磺芭,該方法將返回false赁炎。

切記,不要試圖對(duì)一個(gè)已經(jīng)死亡的線程調(diào)用start()方法使它重新啟動(dòng)徘跪,死亡就是死亡甘邀,該線程將不可再次作為線程執(zhí)行琅攘。

下面程序嘗試對(duì)處于死亡狀態(tài)的線程再次調(diào)用start()垮庐。

package test;

public class StartDead extends Thread {

???private int i;


???// 重寫run方法,run方法的方法體就是線程執(zhí)行體

???public void run() {

??????for (; i < 100; i++) {

?????????System.out.println(getName() + "" + i);

??????}

???}


???public static void main(String[] args) {

??????// 創(chuàng)建線程對(duì)象

??????StartDead sd = new StartDead();

??????for (int i = 0; i < 300; i++) {

?????????// 調(diào)用Thread的currentThread方法獲取當(dāng)前線程

?????????System.out.println(Thread.currentThread().getName() + "" + i);

?????????if (i == 20) {

????????????// 啟動(dòng)線程

????????????sd.start();

????????????// 判斷啟動(dòng)后線程的isAlive()值坞琴,輸出true

????????????System.out.println(sd.isAlive());

?????????}

?????????// 只有當(dāng)線程處于新建哨查、死亡兩種狀態(tài)時(shí)isAlive()方法返回false。

?????????// 當(dāng)i > 20剧辐,則該線程肯定已經(jīng)啟動(dòng)過了寒亥,如果sd.isAlive()為假時(shí),

?????????// 那只能是死亡狀態(tài)了荧关。

?????????if (i > 20 && !sd.isAlive())


?????????{

????????????// 試圖再次啟動(dòng)該線程

?sd.start();

?????????}

??????}

???}

}

4.3 運(yùn)行結(jié)果

main 0

main 1

main 2

main 3

main 4

main 5

main 6

main 7

main 8

main 9

main 10

main 11

main 12

main 13

main 14

main 15

main 16

main 17

main 18

main 19

main 20

true

main 21

…………

Thread-0 0

Thread-0 1

Thread-0 2

Thread-0 3

Thread-0 4

Thread-0 5

Thread-0 6

Thread-0 7

Thread-0 8

………………

Thread-0 92

Thread-0 93

Thread-0 94

Thread-0 95

Thread-0 96

Thread-0 97

Thread-0 98

Thread-0 99

main 25

Exception


main→主線程

Thread-0→線程1

Exception→異常

  上面程序中的粗體字代碼試圖在線程已死亡的情況下再次調(diào)用start()方法來啟動(dòng)該線程溉奕。運(yùn)行上面程序,將引發(fā)IllegaIThreadStateException異常忍啤,這表明處于死亡狀態(tài)的線程無法再次運(yùn)行了加勤。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末仙辟,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子鳄梅,更是在濱河造成了極大的恐慌叠国,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件戴尸,死亡現(xiàn)場(chǎng)離奇詭異粟焊,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)孙蒙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門项棠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人挎峦,你說我怎么就攤上這事沾乘。” “怎么了浑测?”我有些...
    開封第一講書人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵翅阵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我迁央,道長(zhǎng)掷匠,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任岖圈,我火速辦了婚禮讹语,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蜂科。我一直安慰自己顽决,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開白布导匣。 她就那樣靜靜地躺著才菠,像睡著了一般。 火紅的嫁衣襯著肌膚如雪贡定。 梳的紋絲不亂的頭發(fā)上赋访,一...
    開封第一講書人閱讀 49,007評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音缓待,去河邊找鬼蚓耽。 笑死,一個(gè)胖子當(dāng)著我的面吹牛旋炒,可吹牛的內(nèi)容都是我干的步悠。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼瘫镇,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼鼎兽!你這毒婦竟也來了芹壕?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤接奈,失蹤者是張志新(化名)和其女友劉穎踢涌,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體序宦,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡睁壁,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了互捌。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片潘明。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖秕噪,靈堂內(nèi)的尸體忽然破棺而出钳降,到底是詐尸還是另有隱情,我是刑警寧澤腌巾,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布遂填,位于F島的核電站,受9級(jí)特大地震影響澈蝙,放射性物質(zhì)發(fā)生泄漏吓坚。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一灯荧、第九天 我趴在偏房一處隱蔽的房頂上張望礁击。 院中可真熱鬧,春花似錦逗载、人聲如沸哆窿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽挚躯。三九已至,卻和暖如春捏膨,著一層夾襖步出監(jiān)牢的瞬間秧均,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來泰國(guó)打工号涯, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人锯七。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓链快,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親眉尸。 傳聞我的和親對(duì)象是個(gè)殘疾皇子域蜗,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • Java多線程學(xué)習(xí) [-] 一擴(kuò)展javalangThread類 二實(shí)現(xiàn)javalangRunnable接口 三T...
    影馳閱讀 2,952評(píng)論 1 18
  • 本文主要講了java中多線程的使用方法巨双、線程同步、線程數(shù)據(jù)傳遞霉祸、線程狀態(tài)及相應(yīng)的一些線程函數(shù)用法筑累、概述等。 首先講...
    李欣陽閱讀 2,442評(píng)論 1 15
  • 林炳文Evankaka原創(chuàng)作品丝蹭。轉(zhuǎn)載自http://blog.csdn.net/evankaka 本文主要講了ja...
    ccq_inori閱讀 645評(píng)論 0 4
  • ??一個(gè)任務(wù)通常就是一個(gè)程序慢宗,每個(gè)運(yùn)行中的程序就是一個(gè)進(jìn)程。當(dāng)一個(gè)程序運(yùn)行時(shí)奔穿,內(nèi)部可能包含了多個(gè)順序執(zhí)行流镜沽,每個(gè)順...
    OmaiMoon閱讀 1,662評(píng)論 0 12
  • 一、認(rèn)識(shí)多任務(wù)贱田、多進(jìn)程缅茉、單線程、多線程 要認(rèn)識(shí)多線程就要從操作系統(tǒng)的原理說起男摧。 以前古老的DOS操作系統(tǒng)(V 6....
    GT921閱讀 1,011評(píng)論 0 3