国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > Java > 正文

淺析Java線程的中斷機制

2024-07-13 10:15:14
字體:
來源:轉載
供稿:網友

線程中斷機制提供了一種方法,用于將線程從阻塞等待中喚醒,嘗試打斷目標線程的現有處理流程,使之響應新的命令。Java 留給開發者這一自由,我們應當予以善用。
今天我們聊聊 Java 線程的中斷機制。

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

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

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

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

1、超時 1000ms 結束,正常執行下一句代碼。

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

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

這也會正常執行下一句代碼。

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

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

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

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

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--;  }}

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

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

// sun.nio.ch.Interruptiblepublic interface Interruptible {  void interrupt(Thread var1);}// java.lang.Threadprivate 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 flagprivate native void interrupt0();

能夠看出,thread.interrupt() 先判斷權限,然后實際調用 interrupt0() 設置線程的中斷標志,如果當前線程有 nio 的 Interruptible 那么還會回調它。

注意,interrupt0() 只是設置了線程的中斷標志。

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

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

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

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

當一個函數調用會發生阻塞,Java 庫函數在阻塞的源頭簽名里標記 throws InterruptedException,并要求編寫 try catch 處理中斷。

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

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

如果一個線程收到 InterruptedException,之后仍然執行了會引發阻塞的代碼,它將像“沒事人”一樣繼續阻塞住。因為 Java 在內部將中斷標志清除了!

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

將 InterruptedException 交由上層處理。

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

遇到 InterruptedException 重設中斷標志位。

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;  }}

如果一個線程無視中斷標志和 InterruptedException,它仍然能夠跑的很好。但這與我們設計多線程的初衷是違背的,我們希望線程之間是和諧的有序協作以實現特定功能,因此受控線程應當對中斷作出響應。而 Java 留給開發者這一自由,我們應當予以善用。

以上就是這次給大家介紹的Java線程的中斷機制相關知識的全部內容,如果還有任何不明白的可以在下方的留言區域討論,感謝對VeVb武林網的支持。


注:相關教程知識閱讀請移步到JAVA教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 贡觉县| 绥化市| 天水市| 泾阳县| 吕梁市| 孟津县| 乐清市| 石泉县| 凉城县| 开平市| 海宁市| 潜山县| 平顶山市| 连南| 英山县| 揭阳市| 威远县| 广水市| 康保县| 西乡县| 丹棱县| 讷河市| 宁强县| 通化市| 东宁县| 扬中市| 克拉玛依市| 卢龙县| 运城市| 晋江市| 晴隆县| 正蓝旗| 怀来县| 千阳县| 汽车| 循化| 镇远县| 全椒县| 茶陵县| 长海县| 耒阳市|