Thread中interrupt使用方法

合理中斷線程

合理中斷

Thread類中,提供了stop(),suspend()resume()方法,這三個方法分別是用來結束,暫停,恢復線程. 可是都已經被標記爲@Deprecated廢棄了. 由於一個線程不該該由其餘線程來結束,他應該收到別人的通知,而後本身在合適的位置結束,若是不合理的結束,會致使不少意外的結果,好比臨界區還沒徹底操做完,提早釋放鎖,可是部分狀態已經改變,還有沒有作一些清理操做等等.java

基於上面的理由,Java提供了新的中斷機制(interrupt),其餘線程調用想要終止線程的interrupt()方法. 這個時候線程會根據本身的狀態作出響應:ide

  • 若是線程處於阻塞狀態(sleep,wait,join),則線程會拋出InterruptedException異常.
  • 若是線程處於正常運行狀態,則仍是正常運行,可是中斷的標誌被設置爲true,至關於有人通知 你該結束本身了.

被調用線程處於阻塞狀態

public static void main(String[] args) {
    Thread thread = new Thread() {
        @Override
        public void run() {
            try {
                // 被調線程阻塞本身30s
                sleep(30000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    };
    try {
        // 啓動線程
        thread.start();
        // 主線程阻塞本身3秒
        TimeUnit.SECONDS.sleep(3);
        // 中斷線程
        thread.interrupt();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
// ↓ out ↓
// java.lang.InterruptedException: sleep interrupted
// ...

被調用線程處於正常運行

被調用線程不處於阻塞的時候,須要調用方法來監控標誌.spa

public static void main(String[] args) {
    Thread thread = new Thread() {
        @Override
        public void run() {
            while (!Thread.interrupted()) {
                System.out.println("我還穩得住...");
            }
        }
    };
    try {
        thread.start();
        TimeUnit.SECONDS.sleep(3);
        thread.interrupt();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

// ↓ out ↓
// 我能穩得住
// ...

該程序會在檢測interrupt標誌,若是發現interrupt標誌設置爲true,則會結束本身.線程

interrupted()和isInterrupt()的區別

區別: 是否會清除interrupt標誌. isInterrupt()方法不會改變標誌,而interrupted()方法會在檢測的同時,若是發現標誌爲true,則會返回true,而後把標誌置爲false.code

public static void main(String[] args) {
    Thread thread = new Thread() {
        @Override
        public void run() {
            while (!Thread.interrupted()) {
                System.out.println("我還穩得住...");
            }
            // ⚠️⚠️添加下面代碼⚠️⚠️
            System.out.println(Thread.interrupted());
        }
    };
    try {
        thread.start();
        TimeUnit.SECONDS.sleep(3);
        thread.interrupt();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

// ↓ out ↓
// 我還穩得住...
// ...(省略)
// false

上面實例說明Thread.interrupted()方法會在標誌爲true的狀況下修改interrupted的標誌.rem

public static void main(String[] args) {
    Thread thread = new Thread() {
        @Override
        public void run() {
            // ⚠️⚠️修改方法⚠️⚠️
            while (!isInterrupted()) {
                System.out.println("我還穩得住...");
            }
            System.out.println(Thread.interrupted());
        }
    };
    try {
        thread.start();
        TimeUnit.SECONDS.sleep(3);
        thread.interrupt();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

// ↓ out ↓
// 我還穩得住...
// ...(省略)
// true

源碼解析

源碼

經過觀察源碼能夠看出interrupted方法最後會調用isInterrupted(true)方法,而傳入的參數表明是否清除標誌位. 能夠看到isInterrupted(boolean)是一個本地方法,最終會經過C/C++來執行. 而isInterrupted()最後傳入的參數爲false,說明不清除標誌位.源碼

相關文章
相關標籤/搜索