亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

淺析Java線程的中斷機(jī)制

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

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

線程中斷機(jī)制提供了一種方法,有兩種常見(jiàn)用途:

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

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

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

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

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

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

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

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

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

被“中斷”的線程 a,會(huì)在 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)確,因?yàn)?wait 不使用這種“忙輪詢(xún)”的方式做檢查,但關(guān)于標(biāo)志位的判斷邏輯是正確的。

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

// 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)限,然后實(shí)際調(diào)用 interrupt0() 設(shè)置線程的中斷標(biāo)志,如果當(dāng)前線程有 nio 的 Interruptible 那么還會(huì)回調(diào)它。

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

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

怎么檢查?Thread 暴露了兩個(gè)接口,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);

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

當(dāng)一個(gè)函數(shù)調(diào)用會(huì)發(fā)生阻塞,Java 庫(kù)函數(shù)在阻塞的源頭簽名里標(biāo)記 throws InterruptedException,并要求編寫(xiě) 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;

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

我們常見(jiàn)地編寫(xiě)以下三類(lèi)處理 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;
  }
}

如果一個(gè)線程無(wú)視中斷標(biāo)志和 InterruptedException,它仍然能夠跑的很好。但這與我們?cè)O(shè)計(jì)多線程的初衷是違背的,我們希望線程之間是和諧的有序協(xié)作以實(shí)現(xiàn)特定功能,因此受控線程應(yīng)當(dāng)對(duì)中斷作出響應(yīng)。而 Java 留給開(kāi)發(fā)者這一自由,我們應(yīng)當(dāng)予以善用。

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

相關(guān)文章

  • Java雙括弧初始化操作技巧

    Java雙括弧初始化操作技巧

    這篇文章主要介紹了Java雙括弧初始化操作技巧,這種方法不僅提高了代碼的可讀性,而且簡(jiǎn)化了代碼的數(shù)量,需要的朋友可以參考下
    2015-12-12
  • 解析Spring中@Controller@Service等線程安全問(wèn)題

    解析Spring中@Controller@Service等線程安全問(wèn)題

    這篇文章主要為大家介紹解析了Spring中@Controller@Service等線程的安全問(wèn)題,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-03-03
  • Java?9?中的模塊Module系統(tǒng)

    Java?9?中的模塊Module系統(tǒng)

    Java?9?引入的模塊是在Java包(package)的基礎(chǔ)上又引入的一個(gè)新的抽象層,基于package這一點(diǎn)很重要,這里需要強(qiáng)調(diào)一下,接下來(lái)通過(guò)本文給大家介紹Java?9?中的模塊Module系統(tǒng),感興趣的朋友一起看看吧
    2022-03-03
  • SpringMVC中DispatcherServlet的HandlerMapping詳解

    SpringMVC中DispatcherServlet的HandlerMapping詳解

    這篇文章主要介紹了SpringMVC中DispatcherServlet的HandlerMapping詳解,上回說(shuō)的Handler,我們說(shuō)是處理特定請(qǐng)求的,也就是說(shuō),不是所有的請(qǐng)求都能處理,那么問(wèn)題來(lái)了,我們?cè)踔滥膫€(gè)請(qǐng)求是由哪個(gè)Handler處理的呢,需要的朋友可以參考下
    2023-10-10
  • Mybatis實(shí)現(xiàn)自動(dòng)生成增刪改查代碼

    Mybatis實(shí)現(xiàn)自動(dòng)生成增刪改查代碼

    這篇文章主要為大家詳細(xì)介紹了Mybatis如何實(shí)現(xiàn)自動(dòng)生成增刪改查代碼的功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-01-01
  • SpringBoot+Redis海量重復(fù)提交問(wèn)題解決

    SpringBoot+Redis海量重復(fù)提交問(wèn)題解決

    在實(shí)際的開(kāi)發(fā)項(xiàng)目中,一個(gè)對(duì)外暴露的接口往往會(huì)面臨很多次請(qǐng)求,所以本文介紹一下SpringBoot+Redis海量重復(fù)提交問(wèn)題解決,感興趣的可以了解一下
    2023-12-12
  • Java超詳細(xì)講解多態(tài)的調(diào)用

    Java超詳細(xì)講解多態(tài)的調(diào)用

    多態(tài)就是指程序中定義的引用變量所指向的具體類(lèi)型和通過(guò)該引用變量發(fā)出的方法調(diào)用在編程時(shí)并不確定,而是在程序運(yùn)行期間才確定,即一個(gè)引用變量到底會(huì)指向哪個(gè)類(lèi)的實(shí)例對(duì)象,該引用變量發(fā)出的方法調(diào)用到底是哪個(gè)類(lèi)中實(shí)現(xiàn)的方法,必須在由程序運(yùn)行期間才能決定
    2022-05-05
  • Spring Boot Admin微服務(wù)應(yīng)用監(jiān)控的實(shí)現(xiàn)

    Spring Boot Admin微服務(wù)應(yīng)用監(jiān)控的實(shí)現(xiàn)

    這篇文章主要介紹了Spring Boot Admin微服務(wù)應(yīng)用監(jiān)控,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • 使用Springboot自定義注解,支持SPEL表達(dá)式

    使用Springboot自定義注解,支持SPEL表達(dá)式

    這篇文章主要介紹了使用Springboot自定義注解,支持SPEL表達(dá)式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • Java動(dòng)態(tài)規(guī)劃之硬幣找零問(wèn)題實(shí)現(xiàn)示例

    Java動(dòng)態(tài)規(guī)劃之硬幣找零問(wèn)題實(shí)現(xiàn)示例

    本文主要介紹了Java動(dòng)態(tài)規(guī)劃之硬幣找零問(wèn)題實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08

最新評(píng)論