如何正確的處理InterruptedException


何時會出現InterruptedException?

  當一個線程處於阻塞狀態下(例如休眠)的情況下,調用了該線程的interrupt()方法,則會出現InterruptedException。

    @Test
    public void testName() throws Exception {
        // 被中斷的線程
        final Thread t = new Thread(){
            @Override
            public void run() {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    // 當調用t.interrupt(),則會刨除此異常
                    e.printStackTrace();
                }
            }
        };
        // 去中斷t的線程
        new Thread(new Runnable() {
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                t.interrupt();
            }
        }).start();

        t.start();
        t.join();
    }
View Code

先說結論:

  public void interrupt()方法意為向該線程發起中斷請求,所以當出現此異常的情況下,如果該線程在此時應該被中斷,不要吞掉此異常信息,則應該在catch塊里完成任務的情況工作,如果該線程不應該在此時被中斷,則應該調用Thread.currentThread().interrupt() 方法設置中斷標示,讓后續的代碼來檢查並處理異常,通過Thread.interrupted()方法,可以檢查中斷標記。

概括如下:
1.不要生吞此異常;
2.如果可以處理此異常:完成清理工作之后退出;
3.不處理此異常,不繼續執行任務:重新拋出;
4.不處理此異常,繼續執行任務:捕捉到異常之后恢復中斷標記(交由后續程序檢查中斷)。
 
下面對上述提到的Thread.currentThread().interrupt() 和 Thread.interrupted() 二個方法進行解釋:(長相相似,注意區分)

public void interrupt() 方法解釋:

作用:

代替廢棄的stop()方法[暴力停止線程],不直接中止線程,而是傳遞給目標線程一個“應該關閉”的信號,由目標線程自行處理。
“應該關閉”的信號的具體體現:
    當目標線程處於阻塞狀態,會拋出InterruptedException,而不會將標示位設置為true。
    當目標線程處於非阻塞狀態,會將標示位設置為true,不會拋出異常。

應用場景:

取消“可取消的任務”
 
舉例:當用戶發起一項請求,后端的代碼正在進行(可能此任務的代碼運行時間比較長),這個時候用戶想取消這個請求,如果直接調用stop()方法,則此線程會“戛然而止”,我們都知道,web的請求絕大情況下都會有對於數據庫的操作,然后此時線程退出,則事務沒有提交,這就會造成數據不一致的情況;或者該線程正在持有redis中的鎖,那么這樣的話,就會造成鎖不能及時的釋放,所以要使用interrupted()方法,但是這還不夠,我們需要在代碼中適當的位置檢查中斷請求,使用Thread.interrupted()靜態方法,然后返回true,則進行相應的取消處理。

static boolean interrupted() 方法解釋:

作用:測試當前線程是否已被中斷:返回中斷標示位,並且重置中斷標示位為false。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM