不學無數(shù)——InterruptedException異常處理

InterruptedException異常

在了解InterruptedException異常之前應該了解以下的幾個關(guān)于線程的一些基礎(chǔ)知識蝗蛙。而且得知道什么時候會拋InterruptedException異常

當阻塞方法收到中斷請求的時候就會拋出InterruptedException異常

線程的狀態(tài)

線程在一定的條件下會發(fā)生狀態(tài)的改變,下面是線程的一些狀態(tài)

不學無數(shù)
  • 初始(NEW):新建一個線程的對象,還未調(diào)用start方法
  • 運行(RUNNABLE):java線程中將已經(jīng)準備就緒(Ready)和正在運行中(Running)的兩種狀態(tài)都統(tǒng)稱為“Runnable”。準備就緒的線程會被放在線程池中等待被調(diào)用
  • 阻塞(BLOCKED):是因為某種的原因而放棄了CPU的使用權(quán),暫時的停止了運行片酝。直到線程進入準備就緒(Ready)狀態(tài)才會有機會轉(zhuǎn)到運行狀態(tài)
  • 等待(WAITING):該狀態(tài)的線程需要等待其他線程做出一些特定的動作(通知或者是中斷)
  • 超時等待(TIME_WAITING):該狀態(tài)和上面的等待不同,他可以在指定的時間內(nèi)自行返回
  • 終止(TERMINATED):線程任務執(zhí)行完畢

而InterruptedException異常從字面意思上就是中斷異常挖腰,那么什么是中斷呢雕沿?學習中斷之前我們先了解一下具體什么是阻塞

線程阻塞

線程阻塞通常是指一個線程在執(zhí)行過程中暫停,以等待某個條件的觸發(fā)猴仑。而什么情況才會使得線程進入阻塞的狀態(tài)呢审轮?

  • 等待阻塞:運行的線程執(zhí)行wait()方法,該線程會釋放占用的所有資源辽俗,JVM會把該線程放入“等待池”中疾渣。進入這個狀態(tài)后,是不能自動喚醒的崖飘,必須依靠其他線程調(diào)用notify()或notifyAll()方法才能被喚醒
  • 同步阻塞:運行的線程在獲取對象的同步鎖時榴捡,若該同步鎖被別的線程占用,則JVM會把該線程放入“鎖池”中
  • 其他阻塞:運行的線程執(zhí)行sleep()或join()方法朱浴,或者發(fā)出了I/O請求時吊圾,JVM會把該線程置為阻塞狀態(tài)。當sleep()狀態(tài)超時翰蠢、join()等待線程終止或者超時项乒、或者I/O處理完畢時,線程重新轉(zhuǎn)入就緒狀態(tài)

線程中斷

如果我們有一個運行中的軟件梁沧,例如是殺毒軟件正在全盤查殺病毒板丽,此時我們不想讓他殺毒,這時候點擊取消,那么就是正在中斷一個運行的線程埃碱。

每一個線程都有一個boolean類型的標志猖辫,此標志意思是當前的請求是否請求中斷,默認為false砚殿。當一個線程A調(diào)用了線程B的interrupt方法時啃憎,那么線程B的是否請求的中斷標志變?yōu)閠rue。而線程B可以調(diào)用方法檢測到此標志的變化似炎。

  1. 阻塞方法:如果線程B調(diào)用了阻塞方法辛萍,如果是否請求中斷標志變?yōu)榱藅rue,那么它會拋出InterruptedException異常羡藐。拋出異常的同時它會將線程B的是否請求中斷標志置為false
  2. 非阻塞方法:可以通過線程B的isInterrupted方法進行檢測是否請求中斷標志為true還是false贩毕,另外還有一個靜態(tài)的方法interrupted方法也可以檢測標志。但是靜態(tài)方法它檢測完以后會自動的將是否請求中斷標志位置為false仆嗦。例如線程A調(diào)用了線程B的interrupt的方法辉阶,那么如果此時線程B中用靜態(tài)interrupted方法進行檢測標志位的變化的話,那么第一次為true瘩扼,第二次就為false谆甜。下面為具體的例子:
/**
 * @program: Test
 * @description:
 * @author: hu_pf@suixingpay.com
 * @create: 2018-07-31 15:43
 **/
public class InterrupTest implements Runnable{

    public void run(){
            try {
                while (true) {
                    Boolean a = Thread.currentThread().isInterrupted();
                    System.out.println("in run() - about to sleep for 20 seconds-------" + a);
                    Thread.sleep(20000);
                    System.out.println("in run() - woke up");
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();//如果不加上這一句,那么cd將會都是false集绰,因為在捕捉到InterruptedException異常的時候就會自動的中斷標志置為了false
                Boolean c=Thread.interrupted();
                Boolean d=Thread.interrupted();
                System.out.println("c="+c);
                System.out.println("d="+d);
            }
    }
    public static void main(String[] args) {
        InterrupTest si = new InterrupTest();
        Thread t = new Thread(si);
        t.start();
        //主線程休眠2秒规辱,從而確保剛才啟動的線程有機會執(zhí)行一段時間
        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");
    }
}

打印的參數(shù)如下:

in run() - about to sleep for 20 seconds-------false
in main() - interrupting other thread
in main() - leaving
c=true
d=false

現(xiàn)在知道線程可以檢測到自身的標志位的變化,但是他只是一個標志栽燕,如果線程本身不處理的話罕袋,那么程序還是會執(zhí)行下去,就好比碍岔,老師在學校叮囑要好好學習浴讯,具體什么時候,如何好好學習還是看自身付秕。

因此interrupt() 方法并不能立即中斷線程兰珍,該方法僅僅告訴線程外部已經(jīng)有中斷請求侍郭,至于是否中斷還取決于線程自己

InterruptedException異常的處理

簡單的了解了什么是阻塞和中斷以后询吴,我們就該了解碰到InterruptedException異常該如何處理了。

不要不管不顧

有時候阻塞的方法拋出InterruptedException異常并不合適亮元,例如在Runnable中調(diào)用了可中斷的方法猛计,因為你的程序是實現(xiàn)了Runnable接口,然后在重寫Runnable接口的run方法的時候爆捞,那么子類拋出的異常要小于等于父類的異常奉瘤。而在Runnable中run方法是沒有拋異常的。所以此時是不能拋出InterruptedException異常。如果此時你只是記錄日志的話盗温,那么就是一個不負責任的做法藕赞,因為在捕獲InterruptedException異常的時候自動的將是否請求中斷標志置為了false。至少在捕獲了InterruptedException異常之后卖局,如果你什么也不想做斧蜕,那么就將標志重新置為true,以便棧中更高層的代碼能知道中斷砚偶,并且對中斷作出響應批销。

捕獲到InterruptedException異常后恢復中斷狀態(tài)

public class TaskRunner implements Runnable {
    private BlockingQueue<Task> queue;
 
    public TaskRunner(BlockingQueue<Task> queue) { 
        this.queue = queue; 
    }
 
    public void run() { 
        try {
             while (true) {
                 Task task = queue.take(10, TimeUnit.SECONDS);
                 task.execute();
             }
         }
         catch (InterruptedException e) { 
             // Restore the interrupted status
             Thread.currentThread().interrupt();
         }
    }
}

參考文章

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市染坯,隨后出現(xiàn)的幾起案子均芽,更是在濱河造成了極大的恐慌,老刑警劉巖单鹿,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件掀宋,死亡現(xiàn)場離奇詭異,居然都是意外死亡羞反,警方通過查閱死者的電腦和手機布朦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來昼窗,“玉大人是趴,你說我怎么就攤上這事〕尉” “怎么了唆途?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長掸驱。 經(jīng)常有香客問我肛搬,道長,這世上最難降的妖魔是什么毕贼? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任温赔,我火速辦了婚禮,結(jié)果婚禮上鬼癣,老公的妹妹穿的比我還像新娘陶贼。我一直安慰自己,他們只是感情好待秃,可當我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布拜秧。 她就那樣靜靜地躺著,像睡著了一般章郁。 火紅的嫁衣襯著肌膚如雪枉氮。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天,我揣著相機與錄音聊替,去河邊找鬼楼肪。 笑死,一個胖子當著我的面吹牛惹悄,可吹牛的內(nèi)容都是我干的淹辞。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼俘侠,長吁一口氣:“原來是場噩夢啊……” “哼象缀!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起爷速,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤央星,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后惫东,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體莉给,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年廉沮,在試婚紗的時候發(fā)現(xiàn)自己被綠了颓遏。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡滞时,死狀恐怖叁幢,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情坪稽,我是刑警寧澤曼玩,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站窒百,受9級特大地震影響黍判,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜篙梢,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一顷帖、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧渤滞,春花似錦贬墩、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽录肯。三九已至趴腋,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背优炬。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工颁井, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蠢护。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓雅宾,卻偏偏與公主長得像,于是被迫代替她去往敵國和親葵硕。 傳聞我的和親對象是個殘疾皇子眉抬,可洞房花燭夜當晚...
    茶點故事閱讀 42,762評論 2 345

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

  • 任務和線程的啟動很容易。 在大多數(shù)時候懈凹, 我們都會讓它們運行直到結(jié)束蜀变,或者讓它們自行停止。然而介评,有時候我們希望提前...
    好好學習Sun閱讀 1,138評論 0 0
  • 一库北、wait--notify--sleep Object obj = new Object(); obj.wait...
    fe0180bd6eaf閱讀 329評論 0 1
  • 一、并發(fā) 進程:每個進程都擁有自己的一套變量 線程:線程之間共享數(shù)據(jù) 1.線程 Java中為多線程任務提供了很多的...
    SeanMa閱讀 2,405評論 0 11
  • 單任務 單任務的特點是排隊執(zhí)行们陆,也就是同步寒瓦,就像再cmd輸入一條命令后,必須等待這條命令執(zhí)行完才可以執(zhí)行下一條命令...
    Steven1997閱讀 1,166評論 0 6
  • 未折青梅坪仇,青梅枯萎杂腰,余香滿地; 不見竹馬椅文,竹馬老去颈墅,相思萬里。 八十年風雨雾袱,悠悠生死經(jīng)年別恤筛,魂魄不曾入夢; 十八歲...
    何憶飛鴻影閱讀 318評論 13 15