欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java高并發(fā)InterruptedException異常引發(fā)思考

 更新時(shí)間:2022年08月30日 15:25:37   作者:冰_河  
這篇文章主要為大家介紹了java高并發(fā)InterruptedException異常引發(fā)思考,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

前言

InterruptedException異??赡軟](méi)你想的那么簡(jiǎn)單!

當(dāng)我們?cè)谡{(diào)用Java對(duì)象的wait()方法或者線程的sleep()方法時(shí),需要捕獲并處理InterruptedException異常。如果我們對(duì)InterruptedException異常處理不當(dāng),則會(huì)發(fā)生我們意想不到的后果!

程序案例

例如,下面的程序代碼,InterruptedTask類(lèi)實(shí)現(xiàn)了Runnable接口,在run()方法中,獲取當(dāng)前線程的句柄,并在while(true)循環(huán)中,通過(guò)isInterrupted()方法來(lái)檢測(cè)當(dāng)前線程是否被中斷,如果當(dāng)前線程被中斷就退出while(true)循環(huán),同時(shí),在while(true)循環(huán)中,還有一行Thread.sleep(100)代碼,并捕獲了InterruptedException異常。

整個(gè)代碼如下所示。

package io.binghe.concurrent.lab08;
/**
 * @author binghe
 * @version 1.0.0
 * @description 線程測(cè)試中斷
 */
public class InterruptedTask implements Runnable{
    @Override
    public void run() {
        Thread currentThread = Thread.currentThread();
        while (true){
            if(currentThread.isInterrupted()){
                break;
            }
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

上述代碼的本意是通過(guò)isInterrupted()方法檢查線程是否被中斷了,如果中斷了就退出while循環(huán)。其他線程通過(guò)調(diào)用執(zhí)行線程的interrupt()方法來(lái)中斷執(zhí)行線程,此時(shí)會(huì)設(shè)置執(zhí)行線程的中斷標(biāo)志位,從而使currentThread.isInterrupted()返回true,這樣就能夠退出while循環(huán)。

這看上去沒(méi)啥問(wèn)題??!但真的是這樣嗎?我們創(chuàng)建一個(gè)InterruptedTest類(lèi)用于測(cè)試,代碼如下所示。

package io.binghe.concurrent.lab08;
/**
 * @author binghe
 * @version 1.0.0
 * @description 測(cè)試線程中斷
 */
public class InterruptedTest {
    public static void main(String[] args){
        InterruptedTask interruptedTask = new InterruptedTask();
        Thread interruptedThread = new Thread(interruptedTask);
        interruptedThread.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        interruptedThread.interrupt();
    }
}

我們運(yùn)行main方法,如下所示。

這竟然跟我們想象的不一樣!不一樣!不一樣!這是為什么呢?

問(wèn)題分析

上述代碼明明調(diào)用了線程的interrupt()方法來(lái)中斷線程,但是卻并沒(méi)有起到啥作用。原因是線程的run()方法在執(zhí)行的時(shí)候,大部分時(shí)間都是阻塞在sleep(100)上,當(dāng)其他線程通過(guò)調(diào)用執(zhí)行線程的interrupt()方法來(lái)中斷執(zhí)行線程時(shí),大概率的會(huì)觸發(fā)InterruptedException異常,在觸發(fā)InterruptedException異常的同時(shí),JVM會(huì)同時(shí)把線程的中斷標(biāo)志位清除,所以,這個(gè)時(shí)候在run()方法中判斷的currentThread.isInterrupted()會(huì)返回false,也就不會(huì)退出當(dāng)前while循環(huán)了。

既然問(wèn)題分析清除了,那如何中斷線程并退出程序呢?

問(wèn)題解決

正確的處理方式應(yīng)該是在InterruptedTask類(lèi)中的run()方法中的while(true)循環(huán)中捕獲異常之后重新設(shè)置中斷標(biāo)志位,所以,正確的InterruptedTask類(lèi)的代碼如下所示。

package io.binghe.concurrent.lab08;
/**
 * @author binghe
 * @version 1.0.0
 * @description 中斷線程測(cè)試
 */
public class InterruptedTask implements Runnable{
    @Override
    public void run() {
        Thread currentThread = Thread.currentThread();
        while (true){
            if(currentThread.isInterrupted()){
                break;
            }
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
                currentThread.interrupt();
            }
        }
    }
}

可以看到,我們?cè)诓东@InterruptedException異常的catch代碼塊中新增了一行代碼。

currentThread.interrupt();

這就使得我們捕獲到InterruptedException異常后,能夠重新設(shè)置線程的中斷標(biāo)志位,從而中斷當(dāng)前執(zhí)行的線程。

我們?cè)俅芜\(yùn)行InterruptedTest類(lèi)的main方法,如下所示。

總結(jié)

處理InterruptedException異常時(shí)要小心,如果在調(diào)用執(zhí)行線程的interrupt()方法中斷執(zhí)行線程時(shí),拋出了InterruptedException異常,則在觸發(fā)InterruptedException異常的同時(shí),JVM會(huì)同時(shí)把執(zhí)行線程的中斷標(biāo)志位清除,此時(shí)調(diào)用執(zhí)行線程的isInterrupted()方法時(shí),會(huì)返回false。

此時(shí),正確的處理方式是在執(zhí)行線程的run()方法中捕獲到InterruptedException異常,并重新設(shè)置中斷標(biāo)志位(也就是在捕獲InterruptedException異常的catch代碼塊中,重新調(diào)用當(dāng)前線程的interrupt()方法)。

寫(xiě)在最后

最后,附上并發(fā)編程需要掌握的核心技能知識(shí)圖,祝大家在學(xué)習(xí)并發(fā)編程時(shí),少走彎路。

以上就是java高并發(fā)InterruptedException異常引發(fā)思考的詳細(xì)內(nèi)容,更多關(guān)于java高并發(fā)InterruptedException異常的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 教你怎么用SpringBoot+Mybati-Plus快速搭建代碼

    教你怎么用SpringBoot+Mybati-Plus快速搭建代碼

    Mybatis自身通過(guò)了逆向工程來(lái)幫助我們快速生成代碼,但Mybatis-plus卻更加強(qiáng)大,不僅僅可以生成dao,pojo,mapper,還有基本的controller和service層代碼,接下來(lái)我們來(lái)寫(xiě)一個(gè)簡(jiǎn)單的人門(mén)案例是看看如何mybatis-plus是怎么實(shí)現(xiàn)的,需要的朋友可以參考下
    2021-06-06
  • java顯示當(dāng)前運(yùn)行時(shí)的參數(shù)(java運(yùn)行參數(shù))

    java顯示當(dāng)前運(yùn)行時(shí)的參數(shù)(java運(yùn)行參數(shù))

    這篇文章主要介紹了java顯示當(dāng)前運(yùn)行時(shí)參數(shù)的示例(java運(yùn)行參數(shù)),需要的朋友可以參考下
    2014-04-04
  • Spring Boot 如何使用Liquibase 進(jìn)行數(shù)據(jù)庫(kù)遷移(操作方法)

    Spring Boot 如何使用Liquibase 進(jìn)行數(shù)據(jù)庫(kù)遷移(操作方法)

    在Spring Boot應(yīng)用程序中使用Liquibase進(jìn)行數(shù)據(jù)庫(kù)遷移是一種強(qiáng)大的方式來(lái)管理數(shù)據(jù)庫(kù)模式的變化,本文重點(diǎn)講解如何在Spring Boot應(yīng)用程序中使用Liquibase進(jìn)行數(shù)據(jù)庫(kù)遷移,從而更好地管理數(shù)據(jù)庫(kù)模式的變化,感興趣的朋友跟隨小編一起看看吧
    2023-09-09
  • java實(shí)現(xiàn)簡(jiǎn)單計(jì)算器功能

    java實(shí)現(xiàn)簡(jiǎn)單計(jì)算器功能

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)簡(jiǎn)單計(jì)算器功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-12-12
  • Java擦除和轉(zhuǎn)換實(shí)例分析

    Java擦除和轉(zhuǎn)換實(shí)例分析

    這篇文章主要介紹了Java擦除和轉(zhuǎn)換,結(jié)合實(shí)例形式分析了java擦除和轉(zhuǎn)換概念、功能及相關(guān)操作技巧,需要的朋友可以參考下
    2019-07-07
  • MyBatis sql中test如何判斷Boolean

    MyBatis sql中test如何判斷Boolean

    這篇文章主要介紹了MyBatis sql中test如何判斷Boolean,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • Java 中 Map 集合的三種遍歷方式小結(jié)

    Java 中 Map 集合的三種遍歷方式小結(jié)

    這篇文章主要介紹了Java 中 Map 集合的三種遍歷方式,每種遍歷方式結(jié)合示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-12-12
  • Java調(diào)用Shell命令和腳本的實(shí)現(xiàn)

    Java調(diào)用Shell命令和腳本的實(shí)現(xiàn)

    這篇文章主要介紹了Java調(diào)用Shell命令和腳本的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02
  • Java利用文件輸入輸出流實(shí)現(xiàn)文件夾內(nèi)所有文件拷貝到另一個(gè)文件夾

    Java利用文件輸入輸出流實(shí)現(xiàn)文件夾內(nèi)所有文件拷貝到另一個(gè)文件夾

    這篇文章主要介紹了Java實(shí)現(xiàn)文件夾內(nèi)所有文件拷貝到另一個(gè)文件夾,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-03-03
  • Springboot在有鎖的情況下正確使用事務(wù)的實(shí)現(xiàn)代碼

    Springboot在有鎖的情況下正確使用事務(wù)的實(shí)現(xiàn)代碼

    這篇文章主要介紹了Springboot在有鎖的情況下如何正確使用事務(wù),今天通過(guò)一個(gè)實(shí)驗(yàn)給大家分析一下商品超賣(mài)問(wèn)題,模擬場(chǎng)景分析通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2021-12-12

最新評(píng)論