最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

淺析Java線程的中斷機制

 更新時間:2017年12月22日 09:55:32   作者:傅易  
本篇文章通過代碼實例給大家分享了學(xué)習(xí)Java線程的中斷機制的一些心得內(nèi)容,有興趣的朋友學(xué)習(xí)下吧。

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

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

將線程從阻塞等待中喚醒,并作出相應(yīng)的“受控中斷”處理。
嘗試告知目標線程:請打斷現(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 異常。

綜上所述,你可以認為 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--;
  }
}

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

讓我們從上文所述的“手動發(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è)置線程的中斷標志,如果當(dāng)前線程有 nio 的 Interruptible 那么還會回調(diào)它。

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

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

怎么檢查?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ù)需要清空中斷標志。

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

當(dāng)線程發(fā)生了阻塞,就像上文所述,Java 檢查到中斷標志,先將其清除,然后拋出 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)部將中斷標志清除了!

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

將 InterruptedException 交由上層處理。

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

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

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,它仍然能夠跑的很好。但這與我們設(shè)計多線程的初衷是違背的,我們希望線程之間是和諧的有序協(xié)作以實現(xiàn)特定功能,因此受控線程應(yīng)當(dāng)對中斷作出響應(yīng)。而 Java 留給開發(fā)者這一自由,我們應(yīng)當(dāng)予以善用。

以上就是這次給大家介紹的Java線程的中斷機制相關(guān)知識的全部內(nèi)容,如果還有任何不明白的可以在下方的留言區(qū)域討論,感謝對腳本之家的支持。

相關(guān)文章

  • 實例解決Java異常之OutOfMemoryError的問題

    實例解決Java異常之OutOfMemoryError的問題

    在本篇文章中,我們給大家分享了關(guān)于解決Java異常之OutOfMemoryError的問題的方法,有此需要的朋友們學(xué)習(xí)下。
    2019-02-02
  • 利用spring的攔截器自定義緩存的實現(xiàn)實例代碼

    利用spring的攔截器自定義緩存的實現(xiàn)實例代碼

    這篇文章主要介紹了利用spring的攔截器自定義緩存的實現(xiàn)實例代碼,分享了相關(guān)代碼示例,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下
    2018-02-02
  • java通過Arrays.sort(int[] a)實現(xiàn)由大到小排序的方法實現(xiàn)

    java通過Arrays.sort(int[] a)實現(xiàn)由大到小排序的方法實現(xiàn)

    Java中的Arrays.sort()方法是一種內(nèi)置的排序方法,用于對數(shù)組進行排序,本文就來介紹一下java中的Arrays.sort()排序方法的用法,具有一定的參考價值,感興趣的可以了解一下
    2023-12-12
  • java并發(fā)編程專題(十)----(JUC原子類)基本類型詳解

    java并發(fā)編程專題(十)----(JUC原子類)基本類型詳解

    這篇文章主要介紹了java JUC原子類基本類型詳解的相關(guān)資料,文中示例代碼非常詳細,幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • 基于@Valid和@Validated驗證List集合的踩坑記錄

    基于@Valid和@Validated驗證List集合的踩坑記錄

    這篇文章主要介紹了基于@Valid和@Validated驗證List集合的踩坑記錄,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • Java中的AQS框架原理詳解

    Java中的AQS框架原理詳解

    這篇文章主要介紹了Java中的AQS框架原理詳解,AQS核心思想是,如果被請求的共享資源(state)空閑,則將當(dāng)前請求資源的線程設(shè)置為有效的工作線程,并且將共享資源設(shè)置為鎖定狀態(tài),需要的朋友可以參考下
    2023-12-12
  • 詳解Log4j 日志文件存放位置設(shè)置

    詳解Log4j 日志文件存放位置設(shè)置

    這篇文章主要介紹了詳解Log4j 日志文件存放位置設(shè)置,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-08-08
  • 解讀StringBuilder為何比String節(jié)省效率

    解讀StringBuilder為何比String節(jié)省效率

    StringBuilder比String節(jié)省效率的原因主要在于其可變性和性能開銷的降低,StringBuilder在內(nèi)部維護一個字符數(shù)組,可以直接在原有基礎(chǔ)上修改,避免了每次拼接時的額外復(fù)制操作
    2024-12-12
  • Java代理模式實例分析

    Java代理模式實例分析

    這篇文章主要介紹了Java代理模式,結(jié)合實例形式對比分析了java代理模式的使用方法與相關(guān)操作技巧,需要的朋友可以參考下
    2019-07-07
  • idea新建文件后文件夾消失的問題及解決

    idea新建文件后文件夾消失的問題及解決

    這篇文章主要介紹了idea新建文件后文件夾消失的問題及解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-08-08

最新評論

柞水县| 定襄县| 滁州市| 古蔺县| 宜兰市| 手机| 鄯善县| 五常市| 攀枝花市| 成都市| 焉耆| 丰台区| 屯门区| 农安县| 环江| 若尔盖县| 新宾| 苗栗县| 乾安县| 绥化市| 宜城市| 池州市| 高安市| 子长县| 米脂县| 广宗县| 涟源市| 连城县| 安平县| 平顶山市| 闸北区| 崇礼县| 特克斯县| 绥宁县| 中西区| 子长县| 博兴县| 洛隆县| 延长县| 罗田县| 于都县|