Android秀鞭、java中 優(yōu)雅的結(jié)束線程(轉(zhuǎn)載)

<a >文章轉(zhuǎn)自</a></br>


線程對(duì)象屬于一次性消耗品,一般線程執(zhí)行完run方法之后扛禽,線程就正常結(jié)束了锋边,線程結(jié)束之后就報(bào)廢了,不能再次start编曼,只能新建一個(gè)線程對(duì)象豆巨。但有時(shí)run方法是永遠(yuǎn)不會(huì)結(jié)束的。例如在程序中使用線程進(jìn)行Socket監(jiān)聽請(qǐng)求掐场,或是其他的需要循環(huán)處理的任務(wù)往扔。在這種情況下,一般是將這些任務(wù)放在一個(gè)循環(huán)中熊户,如while循環(huán)萍膛。當(dāng)需要結(jié)束線程時(shí),如何退出線程呢嚷堡?

有三種方法可以結(jié)束線程:<br >
  1. 使用退出標(biāo)志蝗罗,使線程正常退出,也就是當(dāng)run方法完成后線程終止蝌戒;

  2. 使用interrupt()方法中斷線程串塑;

  3. 使用stop方法強(qiáng)行終止線程(不推薦使用,可能發(fā)生不可預(yù)料的結(jié)果)北苟。

    前兩種方法都可以實(shí)現(xiàn)線程的正常退出桩匪,也就是要談的優(yōu)雅結(jié)束線程;第3種方法相當(dāng)于電腦斷電關(guān)機(jī)一樣友鼻,是不安全的方法吸祟。

1.使用退出標(biāo)志終止線程</br>

使用一個(gè)變量來控制循環(huán)瑟慈,例如最直接的方法就是設(shè)一個(gè)boolean類型的標(biāo)志桃移,并通過設(shè)置這個(gè)標(biāo)志為true或false來控制while循環(huán)是否退出屋匕。代碼如下:

public class ThreadSafe extends Thread {
    public volatile boolean exit = false; 
        public void run() { 
        while (!exit){
            //do something
        }
    } 
}

</br>
定義了一個(gè)退出標(biāo)志exit,當(dāng)exit為true時(shí)借杰,while循環(huán)退出过吻,exit的默認(rèn)值為false.在定義exit時(shí),使用了一個(gè)Java關(guān)鍵字volatile蔗衡,這個(gè)關(guān)鍵字的目的是使exit同步纤虽,也就是說在同一時(shí)刻只能由一個(gè)線程來修改exit的值。

2.使用interrupt( )方法終止線程

使用interrupt()方法來終端線程可分為兩種情況:
線程處于阻塞狀態(tài)绞惦,如使用了sleep逼纸,同步鎖的wait,socket的receiver济蝉,accept等方法時(shí)杰刽,會(huì)使線程處于阻塞狀態(tài)。當(dāng)調(diào)用線程的interrupt()方法時(shí)王滤,系統(tǒng)會(huì)拋出一個(gè)InterruptedException異常贺嫂,代碼中通過捕獲異常,然后break跳出循環(huán)狀態(tài)雁乡,使線程正常結(jié)束第喳。通常很多人認(rèn)為只要調(diào)用interrupt方法線程就會(huì)結(jié)束,實(shí)際上是錯(cuò)的踱稍,一定要先捕獲InterruptedException異常之后通過break來跳出循環(huán)曲饱,才能正常結(jié)束run方法。

public class ThreadSafe extends Thread {
    public void run() { 
        while (true){
            try{
                    Thread.sleep(5*1000)珠月;阻塞5妙
                }catch(InterruptedException e){
                    e.printStackTrace();
                    break;//捕獲到異常之后扩淀,執(zhí)行break跳出循環(huán)。
                }
        }
    } 
}

線程未進(jìn)入阻塞狀態(tài)桥温,使用isInterrupted()判斷線程的中斷標(biāo)志來退出循環(huán)引矩,當(dāng)使用interrupt()方法時(shí),中斷標(biāo)志就會(huì)置true侵浸,和使用自定義的標(biāo)志來控制循環(huán)是一樣的道理旺韭。

public class ThreadSafe extends Thread {
    public void run() { 
        while (!isInterrupted()){
            //do something, but no tthrow InterruptedException
        }
    } 
}

為什么要區(qū)分進(jìn)入阻塞狀態(tài)和和非阻塞狀態(tài)兩種情況了,是因?yàn)楫?dāng)阻塞狀態(tài)時(shí)掏觉,如果有interrupt()發(fā)生区端,系統(tǒng)除了會(huì)拋出InterruptedException異常外,還會(huì)調(diào)用interrupted()函數(shù)澳腹,調(diào)用時(shí)能獲取到中斷狀態(tài)是true的狀態(tài)织盼,調(diào)用完之后會(huì)復(fù)位中斷狀態(tài)為false杨何,所以異常拋出之后通過isInterrupted()是獲取不到中斷狀態(tài)是true的狀態(tài),從而不能退出循環(huán)沥邻,因此在線程未進(jìn)入阻塞的代碼段時(shí)是可以通過isInterrupted()來判斷中斷是否發(fā)生來控制循環(huán)危虱,在進(jìn)入阻塞狀態(tài)后要通過捕獲異常來退出循環(huán)。因此使用interrupt()來退出線程的最好的方式應(yīng)該是兩種情況都要考慮:

public class ThreadSafe extends Thread {
    public void run() { 
        while (!isInterrupted()){ //非阻塞過程中通過判斷中斷標(biāo)志來退出
            try{
                Thread.sleep(5*1000)唐全;//阻塞過程捕獲中斷異常來退出
            }catch(InterruptedException e){
                e.printStackTrace();
                break;//捕獲到異常之后埃跷,執(zhí)行break跳出循環(huán)。
            }
        }
    } 
}
3.使用stop方法終止線程

程序中可以直接使用thread.stop()來強(qiáng)行終止線程邮利,但是stop方法是很危險(xiǎn)的弥雹,就象突然關(guān)閉計(jì)算機(jī)電源,而不是按正常程序關(guān)機(jī)一樣延届,可能會(huì)產(chǎn)生不可預(yù)料的結(jié)果剪勿,不安全主要是:thread.stop()調(diào)用之后,創(chuàng)建子線程的線程就會(huì)拋出ThreadDeatherror的錯(cuò)誤方庭,并且會(huì)釋放子線程所持有的所有鎖厕吉。一般任何進(jìn)行加鎖的代碼塊,都是為了保護(hù)數(shù)據(jù)的一致性二鳄,如果在調(diào)用thread.stop()后導(dǎo)致了該線程所持有的所有鎖的突然釋放(不可控制)赴涵,那么被保護(hù)數(shù)據(jù)就有可能呈現(xiàn)不一致性,其他線程在使用這些被破壞的數(shù)據(jù)時(shí)订讼,有可能導(dǎo)致一些很奇怪的應(yīng)用程序錯(cuò)誤髓窜。因此,并不推薦使用stop方法來終止線程欺殿。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末寄纵,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子脖苏,更是在濱河造成了極大的恐慌程拭,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件棍潘,死亡現(xiàn)場(chǎng)離奇詭異恃鞋,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)亦歉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門恤浪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人肴楷,你說我怎么就攤上這事水由。” “怎么了?”我有些...
    開封第一講書人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵诀诊,是天一觀的道長(zhǎng)览闰。 經(jīng)常有香客問我哲嘲,道長(zhǎng),這世上最難降的妖魔是什么引几? 我笑而不...
    開封第一講書人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任丹允,我火速辦了婚禮劈彪,結(jié)果婚禮上齿诉,老公的妹妹穿的比我還像新娘筝野。我一直安慰自己,他們只是感情好粤剧,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著挥唠,像睡著了一般抵恋。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上宝磨,一...
    開封第一講書人閱讀 51,688評(píng)論 1 305
  • 那天弧关,我揣著相機(jī)與錄音,去河邊找鬼唤锉。 笑死世囊,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的窿祥。 我是一名探鬼主播株憾,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼晒衩!你這毒婦竟也來了嗤瞎?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤听系,失蹤者是張志新(化名)和其女友劉穎贝奇,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體靠胜,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡掉瞳,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了浪漠。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片陕习。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖郑藏,靈堂內(nèi)的尸體忽然破棺而出衡查,到底是詐尸還是另有隱情,我是刑警寧澤必盖,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布拌牲,位于F島的核電站俱饿,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏塌忽。R本人自食惡果不足惜拍埠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望土居。 院中可真熱鬧枣购,春花似錦、人聲如沸擦耀。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽眷蜓。三九已至分瘾,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間吁系,已是汗流浹背德召。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留汽纤,地道東北人上岗。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像蕴坪,于是被迫代替她去往敵國(guó)和親肴掷。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355

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