線程中斷

什么是線程中斷

Java中斷機(jī)制是一種協(xié)作機(jī)制,也就是說通過中斷并不能直接終止另一個(gè)線程糊昙,而需要被中斷的線程自己處理中斷.
當(dāng)一個(gè)線程運(yùn)行時(shí),另一個(gè)線程可以調(diào)用對應(yīng)的 Thread 對象的 interrupt()方法來中斷它,該方法只是在目標(biāo)線程中設(shè)置一個(gè)標(biāo)志,表示它已經(jīng)被中斷,并立即返回焚廊。這里需要注意的是咆瘟,如果只是單純的調(diào)用 interrupt()方法,線程并沒有實(shí)際被中斷,會(huì)繼續(xù)往下執(zhí)行。
線程自身也可以中斷自身佛嬉。

感性認(rèn)識(shí)中斷

示例代碼

/**
 * Created by haicheng.lhc on 07/07/2017.
 *
 * @author haicheng.lhc
 * @date 2017/07/07
 */
public class TestInterrupt extends Object implements Runnable {

    /**
     *
     */
    public void run() {

        try {
            System.out.println("in run() - about to sleep for 20 seconds");
            Thread.sleep(20000);
            System.out.println("in run() - woke up");
        } catch (InterruptedException e) {
            System.out.println("in run() - interrupted while sleeping");
            //處理完中斷異常后湾揽,返回到run()方法人口,
            //如果沒有return,線程不會(huì)實(shí)際被中斷民晒,它會(huì)繼續(xù)打印下面的信息
            return;
        }
        System.out.println("in run() - leaving normally");

    }

    public static void main(String[] args) {
        TestInterrupt si = new TestInterrupt();
        Thread t = new Thread(si);
        t.start();
        //主線程休眠2秒刮便,從而確保剛才啟動(dòng)的線程有機(jī)會(huì)執(zhí)行一段時(shí)間
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("in main() - interrupting other thread");
        //中斷線程t
        t.interrupt();
        System.out.println("in main() - leaving");
    }
}

結(jié)果是

主線程啟動(dòng)新線程后,自身休眠 2 秒鐘,允許新線程獲得運(yùn)行時(shí)間掂名。新線程打印信息about to sleep for 20 seconds后嗜诀,繼而休眠 20 秒鐘发皿,大約 2 秒鐘后封救,main 線程通知新線程中斷券躁,那么新線程的 20 秒的休眠將被打斷,從而拋出 InterruptException 異常也拜,執(zhí)行跳轉(zhuǎn)到 catch 塊以舒,打印出interrupted while sleeping信息,并立即從 run()方法返回慢哈,然后消亡蔓钟,而不會(huì)打印出 catch 塊后面的leaving normally信息。
另外卵贱,如果將 catch 塊中的 return 語句注釋掉滥沫,則線程在拋出異常后,會(huì)繼續(xù)往下執(zhí)行键俱,而不會(huì)被中斷兰绣,從而會(huì)打印出leaving normally信息。

待決中斷

在上面的例子中编振,sleep()方法的實(shí)現(xiàn)檢查到休眠線程被中斷缀辩,它會(huì)相當(dāng)友好地終止線程,并拋出 InterruptedException 異常。另外一種情況臀玄,如果線程在調(diào)用 sleep()方法前被中斷瓢阴,那么該中斷稱為待決中斷,它會(huì)在剛調(diào)用 sleep()方法時(shí)健无,立即拋出 InterruptedException 異常炫掐。

/**
 * Created by haicheng.lhc on 07/07/2017.
 *
 * @author haicheng.lhc
 * @date 2017/07/07
 */
public class PendingInterrupt extends Object {
    public static void main(String[] args) {
        //如果輸入了參數(shù),則在mian線程中中斷當(dāng)前線程(亦即main線程)
        if (args.length > 0) {
            Thread.currentThread().interrupt();
        }
        //獲取當(dāng)前時(shí)間
        long startTime = System.currentTimeMillis();
        try {
            Thread.sleep(2000);
            System.out.println("was NOT interrupted");
        } catch (InterruptedException x) {
            System.out.println("was interrupted");
        }
        //計(jì)算中間代碼執(zhí)行的時(shí)間
        System.out.println("elapsedTime=" + (System.currentTimeMillis() - startTime));
    }
}

結(jié)果

中斷的原理

Java中斷機(jī)制是一種協(xié)作機(jī)制睬涧,也就是說通過中斷并不能直接終止另一個(gè)線程募胃,而需要被中斷的線程自己處理中斷
Java中斷模型也是這么簡單,每個(gè)線程對象里都有一個(gè)boolean類型的標(biāo)識(shí)(不一定就要是Thread類的字段畦浓,實(shí)際上也的確不是痹束,這幾個(gè)方法最終都是通過native方法來完成的),代表著是否有中斷請求(該請求可以來自所有線程讶请,包括被中斷的線程本身)祷嘶。例如,當(dāng)線程t1想中斷線程t2夺溢,只需要在線程t1中將線程t2對象的中斷標(biāo)識(shí)置為true论巍,然后線程2可以選擇在合適的時(shí)候處理該中斷請求,甚至可以不理會(huì)該請求风响,就像這個(gè)線程沒有被中斷一樣嘉汰。

  • java.lang.Thread類提供了幾個(gè)方法來操作這個(gè)中斷狀態(tài),這些方法包括:
方法名 描述
public static boolean interrupted 測試當(dāng)前線程是否已經(jīng)中斷状勤。線程的中斷狀態(tài) 由該方法清除鞋怀。換句話說,如果連續(xù)兩次調(diào)用該方法持搜,則第二次調(diào)用將返回 false(在第一次調(diào)用已清除了其中斷狀態(tài)之后密似,且第二次調(diào)用檢驗(yàn)完中斷狀態(tài)前,當(dāng)前線程再次中斷的情況除外)葫盼。
public boolean isInterrupted() 測試線程是否已經(jīng)中斷残腌。線程的中斷狀態(tài)不受該方法的影響。
public void interrupt() 中斷線程贫导。
  • interrupt方法是唯一能將中斷狀態(tài)設(shè)置為true的方法抛猫。
  • 靜態(tài)方法interrupted會(huì)將當(dāng)前線程的中斷狀態(tài)清除,但這個(gè)方法的命名極不直觀脱盲,很容易造成誤解

中斷的處理

既然Java中斷機(jī)制只是設(shè)置被中斷線程的中斷狀態(tài)邑滨,那么被中斷線程該做些什么日缨?

1钱反、處理時(shí)機(jī)

顯然,作為一種協(xié)作機(jī)制,不會(huì)強(qiáng)求被中斷線程一定要在某個(gè)點(diǎn)進(jìn)行處理面哥。實(shí)際上哎壳,被中斷線程只需在合適的時(shí)候處理即可,如果沒有合適的時(shí)間點(diǎn)尚卫,甚至可以不處理归榕,這時(shí)候在任務(wù)處理層面,就跟沒有調(diào)用中斷方法一樣吱涉∩残梗“合適的時(shí)候”與線程正在處理的業(yè)務(wù)邏輯緊密相關(guān),例如怎爵,每次迭代的時(shí)候特石,進(jìn)入一個(gè)可能阻塞且無法中斷的方法之前等,但多半不會(huì)出現(xiàn)在某個(gè)臨界區(qū)更新另一個(gè)對象狀態(tài)的時(shí)候鳖链,因?yàn)檫@可能會(huì)導(dǎo)致對象處于不一致狀態(tài)姆蘸。

處理時(shí)機(jī)決定著程序的效率與中斷響應(yīng)的靈敏性。頻繁的檢查中斷狀態(tài)可能會(huì)使程序執(zhí)行效率下降芙委,相反逞敷,檢查的較少可能使中斷請求得不到及時(shí)響應(yīng)。如果發(fā)出中斷請求之后灌侣,被中斷的線程繼續(xù)執(zhí)行一段時(shí)間不會(huì)給系統(tǒng)帶來災(zāi)難推捐,那么就可以將中斷處理放到方便檢查中斷,同時(shí)又能從一定程度上保證響應(yīng)靈敏度的地方侧啼。當(dāng)程序的性能指標(biāo)比較關(guān)鍵時(shí)玖姑,可能需要建立一個(gè)測試模型來分析最佳的中斷檢測點(diǎn),以平衡性能和響應(yīng)靈敏性慨菱。

2焰络、處理方式

(1)中斷狀態(tài)的管理

一般說來,當(dāng)可能阻塞的方法聲明中有拋出InterruptedException則暗示該方法是可中斷的符喝,如BlockingQueue#put闪彼、BlockingQueue#take、Object#wait协饲、Thread#sleep等畏腕,如果程序捕獲到這些可中斷的阻塞方法拋出的InterruptedException或檢測到中斷后,這些中斷信息該如何處理茉稠?一般有以下兩個(gè)通用原則:

  • 如果遇到的是可中斷的阻塞方法拋出InterruptedException描馅,可以繼續(xù)向方法調(diào)用棧的上層拋出該異常,如果是檢測到中斷而线,則可清除中斷狀態(tài)并拋出InterruptedException铭污,使當(dāng)前方法也成為一個(gè)可中斷的方法恋日。

  • 若有時(shí)候不太方便在方法上拋出InterruptedException,比如要實(shí)現(xiàn)的某個(gè)接口中的方法簽名上沒有throws InterruptedException嘹狞,這時(shí)就可以捕獲可中斷方法的InterruptedException并通過Thread.currentThread.interrupt()來重新設(shè)置中斷狀態(tài)岂膳。如果是檢測并清除了中斷狀態(tài),亦是如此磅网。

一般的代碼中谈截,尤其是作為一個(gè)基礎(chǔ)類庫時(shí),絕不應(yīng)當(dāng)吞掉中斷涧偷,即捕獲到InterruptedException后在catch里什么也不做簸喂,清除中斷狀態(tài)后又不重設(shè)中斷狀態(tài)也不拋出InterruptedException等。因?yàn)橥痰糁袛酄顟B(tài)會(huì)導(dǎo)致方法調(diào)用棧的上層得不到這些信息燎潮。

(2)中斷的響應(yīng)

程序里發(fā)現(xiàn)中斷后該怎么響應(yīng)娘赴?這就得視實(shí)際情況而定了。有些程序可能一檢測到中斷就立馬將線程終止跟啤,有些可能是退出當(dāng)前執(zhí)行的任務(wù)诽表,繼續(xù)執(zhí)行下一個(gè)任務(wù)……作為一種協(xié)作機(jī)制,這要與中斷方協(xié)商好隅肥,當(dāng)調(diào)用interrupt會(huì)發(fā)生些什么都是事先知道的竿奏,如做一些事務(wù)回滾操作,一些清理工作腥放,一些補(bǔ)償操作等泛啸。若不確定調(diào)用某個(gè)線程的interrupt后該線程會(huì)做出什么樣的響應(yīng),那就不應(yīng)當(dāng)中斷該線程秃症。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末候址,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子种柑,更是在濱河造成了極大的恐慌岗仑,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,366評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件聚请,死亡現(xiàn)場離奇詭異荠雕,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)驶赏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門炸卑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人煤傍,你說我怎么就攤上這事盖文。” “怎么了蚯姆?”我有些...
    開封第一講書人閱讀 165,689評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵五续,是天一觀的道長洒敏。 經(jīng)常有香客問我,道長返帕,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,925評(píng)論 1 295
  • 正文 為了忘掉前任篙挽,我火速辦了婚禮荆萤,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘铣卡。我一直安慰自己链韭,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,942評(píng)論 6 392
  • 文/花漫 我一把揭開白布煮落。 她就那樣靜靜地躺著敞峭,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蝉仇。 梳的紋絲不亂的頭發(fā)上旋讹,一...
    開封第一講書人閱讀 51,727評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音轿衔,去河邊找鬼沉迹。 笑死,一個(gè)胖子當(dāng)著我的面吹牛害驹,可吹牛的內(nèi)容都是我干的鞭呕。 我是一名探鬼主播,決...
    沈念sama閱讀 40,447評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼宛官,長吁一口氣:“原來是場噩夢啊……” “哼葫松!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起底洗,我...
    開封第一講書人閱讀 39,349評(píng)論 0 276
  • 序言:老撾萬榮一對情侶失蹤腋么,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后亥揖,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體党晋,經(jīng)...
    沈念sama閱讀 45,820評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,990評(píng)論 3 337
  • 正文 我和宋清朗相戀三年徐块,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了未玻。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,127評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡胡控,死狀恐怖扳剿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情昼激,我是刑警寧澤庇绽,帶...
    沈念sama閱讀 35,812評(píng)論 5 346
  • 正文 年R本政府宣布锡搜,位于F島的核電站,受9級(jí)特大地震影響瞧掺,放射性物質(zhì)發(fā)生泄漏耕餐。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,471評(píng)論 3 331
  • 文/蒙蒙 一辟狈、第九天 我趴在偏房一處隱蔽的房頂上張望肠缔。 院中可真熱鬧,春花似錦哼转、人聲如沸明未。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽趟妥。三九已至,卻和暖如春佣蓉,著一層夾襖步出監(jiān)牢的瞬間披摄,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評(píng)論 1 272
  • 我被黑心中介騙來泰國打工勇凭, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留行疏,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,388評(píng)論 3 373
  • 正文 我出身青樓套像,卻偏偏與公主長得像酿联,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子夺巩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,066評(píng)論 2 355

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

  • 一贞让、前言 所謂線程中斷,其實(shí)就是終止一個(gè)線程柳譬。在使用 Java 線程時(shí)喳张,除了線程自行正常結(jié)束,很多時(shí)候也需要提前結(jié)...
    編走編想閱讀 1,524評(píng)論 2 9
  • 中斷線程 thread.interrupt()用來中斷線程美澳,即將線程的中斷狀態(tài)位設(shè)置為true销部,注意中斷操作并不會(huì)...
    劉建會(huì)閱讀 2,558評(píng)論 0 1
  • 為什么要中斷 Java中沒有一種安全的搶占方法來停止線程,也沒有安全的搶占方式停止任務(wù)制跟,只有一些協(xié)作機(jī)制舅桩。 更好的...
    zlcook閱讀 582評(píng)論 0 0
  • 前面的幾篇文章主要介紹了線程的一些最基本的概念,包括線程的間的沖突及其解決辦法雨膨,以及線程間的協(xié)作機(jī)制擂涛。本篇主要來學(xué)...
    Single_YAM閱讀 478評(píng)論 0 3
  • 在人生的許多階段,我都想到過聊记,如果就這樣死了撒妈,也許是件好事恢暖。這樣想的時(shí)候,往往腦海中想到的是最至親的人狰右。 除非真的...
    佳佳的寶瓶子閱讀 1,474評(píng)論 0 0