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

JAVA多線程之中斷機(jī)制及處理中斷的方法

 更新時(shí)間:2023年02月13日 09:43:07   作者:大熊貓同學(xué)  
這篇文章主要記錄使用 interrupt() 方法中斷線程,以及如何對(duì)InterruptedException進(jìn)行處理,感覺對(duì)InterruptedException異常進(jìn)行處理是一件謹(jǐn)慎且有技巧的活兒,需要的朋友可以參考下

一,介紹

這篇文章主要記錄使用 interrupt() 方法中斷線程,以及如何對(duì)InterruptedException進(jìn)行處理。感覺對(duì)InterruptedException異常進(jìn)行處理是一件謹(jǐn)慎且有技巧的活兒。

由于使用stop()方法停止線程非常的暴力,人家線程運(yùn)行的好好的,突然就把人家殺死了,線程占用的鎖被強(qiáng)制釋放,極易導(dǎo)致數(shù)據(jù)的不一致性??蓞⒖歼@篇文章對(duì)stop()方法的介紹。

因此,提出了一種溫和的方式:請(qǐng)求另外一個(gè)線程不要再執(zhí)行了,這就是中斷方式。

二,中斷及如何響應(yīng)中斷?

如何優(yōu)雅地響應(yīng)中斷真的是太高深了,看到這篇文章:Java 理論與實(shí)踐: 處理 InterruptedException就嚇了一跳。下面只是記錄一些最簡單的我對(duì)響應(yīng)中斷的理解。

假設(shè)某個(gè)線程要不停地處理某件事情(比如 i 一直自增),但是還有個(gè)要求:在處理事情前,先要檢查下這個(gè)線程是否被中斷,如果已經(jīng)被中斷,處理就應(yīng)該結(jié)束。

下面是一些例子,這些例子摘自書本:

public class Run {

    public static void main(String[] args) {
        try {
            MyThread thread = new MyThread();
            thread.start();
            Thread.sleep(20);//modify 2000 to 20
            thread.interrupt();//請(qǐng)求中斷MyThread線程
        } catch (InterruptedException e) {
            System.out.println("main catch");
            e.printStackTrace();
        }
        System.out.println("end!");
    }
}

main線程睡眠20ms后,執(zhí)行第8行中斷MyThread線程。

在《java并發(fā)編程實(shí)戰(zhàn)》中有一句話:“對(duì)中斷操作的正確理解是:它并不會(huì)真正地中斷一個(gè)線程,而只是發(fā)出中斷請(qǐng)求,然后由線程在下一個(gè)合適的時(shí)刻中斷自己”。以上面的示例對(duì)這句話作一個(gè)解讀,如下:

1、main線程向 MyThread線程發(fā)出了中斷請(qǐng)求

2、假如 MyThread線程此刻正在執(zhí)行第10行,打印。對(duì)于 MyThread線程來說,此時(shí)并不是一個(gè)“合適”的時(shí)刻。因?yàn)椋杭热粓?zhí)行到了 println語句的地方,那就應(yīng)該把 i的值打印出來,這樣才是一種“一致的狀態(tài)”。關(guān)于一致狀態(tài)的理解,可參考書中的一段話:(在 java中沒有一種安全的搶占式方法來停止線程,而是一種“協(xié)作”方式,它能夠使用“共享的數(shù)據(jù)結(jié)構(gòu)”盡可能地處于一致的狀態(tài))

3、既然第10行不是一個(gè)合適的時(shí)刻,那么:“下一個(gè)合適的時(shí)刻”到底在哪里?答案就是:第6行的 if語句。因?yàn)樵诘?行,MyThread線程檢測(cè)到了 main線程的中斷請(qǐng)求,于是:break for循環(huán),滿足程序的“執(zhí)行語義”。在這里,執(zhí)行語義是:遍歷一次 for循環(huán),就打印出 i

public class MyThread extends Thread {
    @Override
    public void run() {
        super.run();
        for (int i = 0; i < 500000; i++) {
            if (this.interrupted()) {
                System.out.println("should be stopped and exit");
                break;
            }
            System.out.println("i=" + (i + 1));
        }
        System.out.println("this line is also executed. thread does not stopped");//盡管線程被中斷,但并沒有結(jié)束運(yùn)行。這行代碼還是會(huì)被執(zhí)行
    }
}

當(dāng)MyThread獲得CPU執(zhí)行時(shí),第6行的 if 測(cè)試中,檢測(cè)到中斷標(biāo)識(shí)被設(shè)置。即MyThread線程檢測(cè)到了main線程想要中斷它的 請(qǐng)求。

大多數(shù)情況下,MyThread檢測(cè)到了中斷請(qǐng)求,對(duì)該中斷的響應(yīng)是:退出執(zhí)行(或者說是結(jié)束執(zhí)行)。

但是,上面第5至8行for循環(huán),是執(zhí)行break語句跳出for循環(huán)。但是,線程并沒有結(jié)束,它只是跳出了for循環(huán)而已,它還會(huì)繼續(xù)執(zhí)行第12行的代碼....

因此,我們的問題是,當(dāng)收到了中斷請(qǐng)求后,如何結(jié)束該線程呢?

一種可行的方法是使用 return 語句 而不是 break語句。。。。。哈哈。。。

當(dāng)然,一種更優(yōu)雅的方式則是:拋出InterruptedException異常。

看下面MyThread類的代碼:

public class MyThread extends Thread {
    @Override
    public void run() {
        super.run();
        try{
            for (int i = 0; i < 500000; i++) {
                if (this.interrupted()) {
                    System.out.println("should be stopped and exit");
                    throw new InterruptedException();
                }
                System.out.println("i=" + (i + 1));
            }
            System.out.println("this line cannot be executed. cause thread throws exception");//這行語句不會(huì)被執(zhí)行!!!
        }catch(InterruptedException e){
            System.out.println("catch interrupted exception");
            e.printStackTrace();
        }
    }
}

當(dāng)MyThread線程檢測(cè)到中斷標(biāo)識(shí)為true后,在第9行拋出InterruptedException異常。這樣,該線程就不能再執(zhí)行其他的正常語句了(如,第13行語句不會(huì)執(zhí)行)。這里表明:interrupt()方法有兩個(gè)作用,一個(gè)是將線程的中斷狀態(tài)置位(中斷狀態(tài)由false變成true);另一個(gè)則是:讓被中斷的線程拋出InterruptedException異常。

這是很重要的。這樣,對(duì)于那些阻塞方法(比如 wait() 和 sleep())而言,當(dāng)另一個(gè)線程調(diào)用interrupt()中斷該線程時(shí),該線程會(huì)從阻塞狀態(tài)退出并且拋出中斷異常。這樣,我們就可以捕捉到中斷異常,并根據(jù)實(shí)際情況對(duì)該線程從阻塞方法中異常退出而進(jìn)行一些處理。

比如說:線程A獲得了鎖進(jìn)入了同步代碼塊中,但由于條件不足調(diào)用 wait() 方法阻塞了。這個(gè)時(shí)候,線程B執(zhí)行 threadA.interrupt()請(qǐng)求中斷線程A,此時(shí)線程A就會(huì)拋出InterruptedException,我們就可以在catch中捕獲到這個(gè)異常并進(jìn)行相應(yīng)處理(比如進(jìn)一步往上拋出)

因此,上面就是一個(gè)采用拋出異常的方式來結(jié)束線程的示例。盡管該示例的實(shí)用性不大。原因在 IBM的這篇博文中:我們 生吞了中斷。

在第14行,我們直接catch了異常,然后打印輸出了一下而已,調(diào)用棧中的更高層的代碼是無法獲得關(guān)于該異常的信息的。

第16行的e.printStackTrace()作用就相當(dāng)于

“(僅僅記錄 InterruptedException 也不是明智的做法,因?yàn)榈鹊饺藖碜x取日志的時(shí)候,再來對(duì)它作出處理就為時(shí)已晚了。)”---摘自參考博文

上面我們是在run()方法中拋出異常,符合這里描述的:

有時(shí)候拋出 InterruptedException 并不合適,例如當(dāng)由 Runnable 定義的任務(wù)調(diào)用一個(gè)
可中斷的方法時(shí),就是如此。在這種情況下,不能重新拋出 InterruptedException,但是
您也不想什么都不做。當(dāng)一個(gè)阻塞方法檢測(cè)到中斷并拋出 InterruptedException 時(shí),它
清除中斷狀態(tài)。如果捕捉到 InterruptedException 但是不能重新拋出它,那么應(yīng)該保留
中斷發(fā)生的證據(jù),以便調(diào)用棧中更高層的代碼能知道中斷,并對(duì)中斷作出響應(yīng)。該任務(wù)可以
通過調(diào)用 interrupt() 以 “重新中斷” 當(dāng)前線程來完成,如清單 3 所示。 -----“摘自參考博文”

因?yàn)?,run方法是實(shí)現(xiàn)的Runnable接口中的方法。不能像下面這樣定義,也即上面所說的:“不能重新拋出InterruptedException”。

 @Override
        public void run() throws InterruptedException{//這是錯(cuò)誤的
          //do something...

因此,一個(gè)更好的解決方案是:調(diào)用 interrupt() 以 “重新中斷” 當(dāng)前線程。改進(jìn)MyThread類中catch異常的方式,如下:

public class MyThread extends Thread {
    @Override
    public void run() {
        super.run();
        try{
            for (int i = 0; i < 500000; i++) {
                if (this.interrupted()) {
                    System.out.println("should be stopped and exit");
                    throw new InterruptedException();
                }
                System.out.println("i=" + (i + 1));
            }
            System.out.println("this line cannot be executed. cause thread throws exception");
        }catch(InterruptedException e){
            /**這樣處理不好
             * System.out.println("catch interrupted exception");
             * e.printStackTrace();
             */
             Thread.currentThread().interrupt();//這樣處理比較好
        }
    }
}

這樣,就由 生吞異常 變成了 將 異常事件 進(jìn)一步擴(kuò)散了。

參考博文:Java 理論與實(shí)踐: 處理 InterruptedException

參考書籍:《Java多線程編程核心技術(shù)》

到此這篇關(guān)于JAVA多線程之中斷機(jī)制及處理中斷的方法的文章就介紹到這了,更多相關(guān)java多線程中斷機(jī)制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java如何實(shí)現(xiàn)雙向鏈表功能

    Java如何實(shí)現(xiàn)雙向鏈表功能

    雙向鏈表也叫雙鏈表,是鏈表的一種,它的每個(gè)數(shù)據(jù)結(jié)點(diǎn)中都有兩個(gè)指針,分別指向直接后繼和直接前驅(qū)。所以,從雙向鏈表中的任意一個(gè)結(jié)點(diǎn)開始,都可以很方便地訪問它的前驅(qū)結(jié)點(diǎn)和后繼結(jié)點(diǎn)。一般我們都構(gòu)造雙向循環(huán)鏈表
    2021-11-11
  • java -D參數(shù)設(shè)置系統(tǒng)屬性無效問題及解決

    java -D參數(shù)設(shè)置系統(tǒng)屬性無效問題及解決

    這篇文章主要介紹了java -D參數(shù)設(shè)置系統(tǒng)屬性無效問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • Java contains用法示例

    Java contains用法示例

    這篇文章主要介紹了Java contains的用法示例,幫助大家更好的理解和學(xué)習(xí)Java,感興趣的朋友可以了解下
    2020-11-11
  • mybatisplus的邏輯刪除問題

    mybatisplus的邏輯刪除問題

    這篇文章主要介紹了mybatisplus的邏輯刪除問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • 最新IDEA?2022基于JVM極致優(yōu)化?IDEA啟動(dòng)速度的方法

    最新IDEA?2022基于JVM極致優(yōu)化?IDEA啟動(dòng)速度的方法

    這篇文章主要介紹了IDEA?2022最新版?基于?JVM極致優(yōu)化?IDEA?啟動(dòng)速度,需要的朋友可以參考下
    2022-08-08
  • Android圖片轉(zhuǎn)換器代碼分享

    Android圖片轉(zhuǎn)換器代碼分享

    本文給大家總結(jié)了下在安卓程序中進(jìn)行圖片轉(zhuǎn)換的方法,非常的實(shí)用,小伙伴們可以參考下。
    2015-10-10
  • Java實(shí)現(xiàn)的生成二維碼統(tǒng)計(jì)掃描次數(shù)并轉(zhuǎn)發(fā)到某個(gè)地址功能詳解

    Java實(shí)現(xiàn)的生成二維碼統(tǒng)計(jì)掃描次數(shù)并轉(zhuǎn)發(fā)到某個(gè)地址功能詳解

    這篇文章主要介紹了Java實(shí)現(xiàn)的生成二維碼統(tǒng)計(jì)掃描次數(shù)并轉(zhuǎn)發(fā)到某個(gè)地址功能,可實(shí)現(xiàn)生成帶統(tǒng)計(jì)功能的二維碼,涉及java二維碼的生成、參數(shù)傳遞、解析等相關(guān)操作技巧,需要的朋友可以參考下
    2018-07-07
  • IDEA自定義pom依賴的步驟詳解

    IDEA自定義pom依賴的步驟詳解

    這篇文章主要介紹了IDEA自定義pom依賴的步驟詳解,本文分步驟通過圖文并茂的形式給大家介紹的非常詳細(xì)對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-04-04
  • MyBatisPlus的簡介及案例詳解

    MyBatisPlus的簡介及案例詳解

    MyBatisPlus(簡稱MP)是基于MyBatis框架基礎(chǔ)上開發(fā)的增強(qiáng)型工具,旨在簡化開發(fā)、提高效率。本文將為大家詳細(xì)介紹一下MyBatisPlus是使用,需要的可以參考一下
    2022-07-07
  • IDEA運(yùn)行SSM項(xiàng)目的超詳細(xì)圖解教程

    IDEA運(yùn)行SSM項(xiàng)目的超詳細(xì)圖解教程

    SSM項(xiàng)目部署其實(shí)很簡單,下面這篇文章主要給大家介紹了關(guān)于IDEA運(yùn)行SSM項(xiàng)目的超詳細(xì)圖解教程,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2023-10-10

最新評(píng)論