天天看點

Java 06 - interruptinterrupt

interrupt

原理

interrupt是Thread中的一個方法, 其本質是将線程中的中斷标志設定為true, 而不是直接中斷. 設定後, 根據線程的狀态而有不同的後續操作. 如果, 線程的目前狀态處于非阻塞狀态, 那麼僅僅是線程的中斷标志被改為了true, 一旦線程調用了wait, join, sleep方法中的一種, 立馬抛出InterruptedException, 并将中斷标志重置, 重新設定為false. 如果線程目前狀态處于阻塞狀态, 那麼會有三種情況之一:

  • 如果是wait, join, sleep三個方法引起的阻塞, 那麼線程的中斷标志會重置為false, 并且抛出一個InterruptedException.
  • 如果是java.nio.channels.InterruptibleChannel進行的IO阻塞, 會抛出ClosedByInterruptedException.
  • 如果是java.nio.channels.Selectors引起的阻塞, 則立即傳回, 不會抛出異常.

循環體中catch

對InterruptedException的捕獲一般放在while循環體的外面, 這樣在産生異常的時候就退出了while循環, 否則InterruptedException在while之内, 就需要添加額外的退出處理.

@Override
public void run() {
    while(true) {
        try {
            // todo
        } catch(InterruptedException) {
            // todo
            break;
        }
    }
}           

複制

isInterrupted()

@Override
public void run() {
    while(!isInterrupted()) {
        // todo
    }
}           

複制

isInterrupted()可以傳回中斷标志位的值, 表示運作中的線程是否被Thread.Interrupt()調用.

interrputed()

Interrupted()和isInterrupted()都可以傳回中斷标志位的值, 不同的是, 前者還會将中斷标志位重置為false.

中斷狀态與InterruptedException

調用Interrupt方法後, 可以中斷掉線程. 這裡的中斷是指:

  1. 線程變成”中斷狀态”.
  2. 線程catch到InterruptedException後的邏輯操作.

因為我們知道, 如果調用了interrput方法, 但是線程的狀态并不是在join, wait, sleep的話, 并不會抛出InterruptedException, 而是将interrupt标志位設為true, 這就是線程的”中斷狀态”.

中斷狀态 -> InterruptedException異常的轉換:

如果線程是中斷狀态, 那麼抛出InterruptedException異常:

if(Thread.interrupted()) {
    throw new InterruptedException();
}           

複制

這樣可以提高線程對于interrupt()的響應性. 注意Thread.interrupted()會抹掉标志位的值, 使其變成false. 如果不想對标志位改動, 可以調用Thread.currentThread().isInterrupted()方法.

InterruptedException異常 -> 中斷狀态的轉換:

try {
    Thread.sleep(1000);
} catch(InterruptedException e) {
    Thread.currentThread().interrput();
}           

複制

InterruptedException異常 -> InterruptedException異常:

InterruptedException savedInterruption = null;

try {
    Thread.sleep(1000);
} catch (InterrputionException e) {
    savedException = e;
}

if(savedException != null) {
    throw savedException;
}           

複制

延遲抛出異常.

注意

處于wait态中的線程在被interrupt後, 會跳出wait set, 并在下次獲得Object鎖的時候, 才會抛出InterruptedException.