溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Java線程中斷機制的示例分析

發(fā)布時間:2021-08-21 14:17:26 來源:億速云 閱讀:123 作者:小新 欄目:編程語言

這篇文章主要為大家展示了“Java線程中斷機制的示例分析”,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“Java線程中斷機制的示例分析”這篇文章吧。

線程中斷機制提供了一種方法,用于將線程從阻塞等待中喚醒,嘗試打斷目標(biāo)線程的現(xiàn)有處理流程,使之響應(yīng)新的命令。

線程中斷機制提供了一種方法,有兩種常見用途:

將線程從阻塞等待中喚醒,并作出相應(yīng)的“受控中斷”處理。
嘗試告知目標(biāo)線程:請打斷現(xiàn)有處理流程,響應(yīng)新的命令。
以第一種用途為例,請看以下代碼:

synchronized (lock) {
  try {
    while (!check()) {
      lock.wait(1000);
    }
  } catch (InterruptedException e) {
    e.printStackTrace();
  }
}

這段代碼使用了 Java 提供的 wait/notify 機制,線程執(zhí)行 lock.wait() 會阻塞,有三種情況使線程恢復(fù)運行。

1、超時 1000ms 結(jié)束,正常執(zhí)行下一句代碼。

2、另一個線程執(zhí)行下述代碼主動喚醒

synchronized (lock) {
  lock.notifyAll(); // or lock.notify();
}

這也會正常執(zhí)行下一句代碼。

3、另一個線程要求等待的線程“中斷”

// 拿到等待中的線程的引用
Thread a;
a.interrupt();

被“中斷”的線程 a,會在 lock.wait() 處拋出 InterruptedException 異常。

綜上所述,你可以認(rèn)為 object.wait() 內(nèi)部在做這些事:

boolean checkTimeout = timeout > 0;
Thread current = Thread.currentThread();
lock.addWaiter(current);
while (!current.isNotified()) {
  if (current.isInterrupted()) {
    current.clearInterrupted();
    throw new InterruptedException();
  }
  if (checkTimeout) {
    if (timeout == 0) break;
    timeout--;
  }
}

這不完全準(zhǔn)確,因為 wait 不使用這種“忙輪詢”的方式做檢查,但關(guān)于標(biāo)志位的判斷邏輯是正確的。

讓我們從上文所述的“手動發(fā)出中斷”這一操作開始探究

// sun.nio.ch.Interruptible
public interface Interruptible {
  void interrupt(Thread var1);
}
// java.lang.Thread
private volatile Interruptible blocker;
private final Object blockerLock = new Object();
public void interrupt() {
  if (this != Thread.currentThread())
    checkAccess();
  synchronized (blockerLock) {
    Interruptible b = blocker;
    if (b != null) {
      interrupt0();
      b.interrupt(this);
      return;
    }
  }
  interrupt0();
}
// Just to set the interrupt flag
private native void interrupt0();

能夠看出,thread.interrupt() 先判斷權(quán)限,然后實際調(diào)用 interrupt0() 設(shè)置線程的中斷標(biāo)志,如果當(dāng)前線程有 nio 的 Interruptible 那么還會回調(diào)它。

注意,interrupt0() 只是設(shè)置了線程的中斷標(biāo)志。

當(dāng)一個線程并不阻塞,沒有在 object.wait(), thread.join(), Thread.sleep() 等不受 Java 程序邏輯控制的區(qū)域時,那么會發(fā)生什么事情?答案是不會發(fā)生任何事情,線程是否被打斷只能通過主動地檢查中斷標(biāo)志得知。

怎么檢查?Thread 暴露了兩個接口,Thread.interrupted() 和 thread.isInterrupted()。

// java.lang.Thread
public static boolean interrupted() {
  return currentThread().isInterrupted(true);
}
public boolean isInterrupted() {
  return isInterrupted(false);
}
private native boolean isInterrupted(boolean clearInterrupted);

能夠看出,兩者都是依靠內(nèi)部的 isInterrupted(boolean),而它會返回線程是否被打斷,并根據(jù)需要清空中斷標(biāo)志。

當(dāng)一個函數(shù)調(diào)用會發(fā)生阻塞,Java 庫函數(shù)在阻塞的源頭簽名里標(biāo)記 throws InterruptedException,并要求編寫 try catch 處理中斷。

當(dāng)線程發(fā)生了阻塞,就像上文所述,Java 檢查到中斷標(biāo)志,先將其清除,然后拋出 InterruptedException。

// java.lang.Object
public final void wait() throws InterruptedException {
  wait(0);
}
public final native void wait(long timeout) throws InterruptedException;

如果一個線程收到 InterruptedException,之后仍然執(zhí)行了會引發(fā)阻塞的代碼,它將像“沒事人”一樣繼續(xù)阻塞住。因為 Java 在內(nèi)部將中斷標(biāo)志清除了!

我們常見地編寫以下三類處理 InterruptedException 的代碼:

將 InterruptedException 交由上層處理。

public void foo() throws InterruptedException {
  synchronized (lock) {
    lock.wait();
  }
}

遇到 InterruptedException 重設(shè)中斷標(biāo)志位。

try {
  synchronized (lock) { 
    lock.wait(); 
  } 
} catch (InterruptedException e) { 
  Thread.currentThread().interrupt();
  //break; 
}

先忙完,再重新拋出 InterruptedException。

public void bar() throws InterruptedException {
  InterruptedException ie = null;
  boolean done = false;
  while (!done) {
    synchronized (lock) {
      try {
        lock.wait();
      } catch (InterruptedException e) {
        ie = e;
        continue;
      }
    }
    done = true;
  }
  if (ie != null) {
    throw ie;
  }
}

如果一個線程無視中斷標(biāo)志和 InterruptedException,它仍然能夠跑的很好。但這與我們設(shè)計多線程的初衷是違背的,我們希望線程之間是和諧的有序協(xié)作以實現(xiàn)特定功能,因此受控線程應(yīng)當(dāng)對中斷作出響應(yīng)。

以上是“Java線程中斷機制的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI