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

JAVA多線程之中斷機制及處理中斷的方法

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

一,介紹

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

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

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

二,中斷及如何響應中斷?

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

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

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

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();//請求中斷MyThread線程
        } catch (InterruptedException e) {
            System.out.println("main catch");
            e.printStackTrace();
        }
        System.out.println("end!");
    }
}

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

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

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

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

3、既然第10行不是一個合適的時刻,那么:“下一個合適的時刻”到底在哪里?答案就是:第6行的 if語句。因為在第6行,MyThread線程檢測到了 main線程的中斷請求,于是: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");//盡管線程被中斷,但并沒有結束運行。這行代碼還是會被執(zhí)行
    }
}

當MyThread獲得CPU執(zhí)行時,第6行的 if 測試中,檢測到中斷標識被設置。即MyThread線程檢測到了main線程想要中斷它的 請求。

大多數(shù)情況下,MyThread檢測到了中斷請求,對該中斷的響應是:退出執(zhí)行(或者說是結束執(zhí)行)。

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

因此,我們的問題是,當收到了中斷請求后,如何結束該線程呢?

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

當然,一種更優(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");//這行語句不會被執(zhí)行!!!
        }catch(InterruptedException e){
            System.out.println("catch interrupted exception");
            e.printStackTrace();
        }
    }
}

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

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

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

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

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

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

“(僅僅記錄 InterruptedException 也不是明智的做法,因為等到人來讀取日志的時候,再來對它作出處理就為時已晚了。)”---摘自參考博文

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

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

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

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

因此,一個更好的解決方案是:調(diào)用 interrupt() 以 “重新中斷” 當前線程。改進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();//這樣處理比較好
        }
    }
}

這樣,就由 生吞異常 變成了 將 異常事件 進一步擴散了。

參考博文:Java 理論與實踐: 處理 InterruptedException

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

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

相關文章

  • 解析Idea為什么不推薦使用@Autowired進行Field注入

    解析Idea為什么不推薦使用@Autowired進行Field注入

    這篇文章主要介紹了Idea不推薦使用@Autowired進行Field注入的原因,網(wǎng)上文章大部分都是介紹兩者的區(qū)別,沒有提到為什么,當時想了好久想出了可能的原因,今天來總結一下
    2022-05-05
  • SpringCloudAlibaba微服務調(diào)用組件OpenFeign的方法

    SpringCloudAlibaba微服務調(diào)用組件OpenFeign的方法

    Feign是Netflix開發(fā)的聲明式、模板化的HTTP客戶端,其靈感來自Retrofit、JAXRS-2.0以及WebSocket,Feign可幫助我們更加便捷、優(yōu)雅地調(diào)用HTTP API,這篇文章主要介紹了SpringCloudAlibaba微服務調(diào)用組件OpenFeign,需要的朋友可以參考下
    2024-07-07
  • SpringBoot實現(xiàn)多數(shù)據(jù)源的切換實踐

    SpringBoot實現(xiàn)多數(shù)據(jù)源的切換實踐

    這篇主要介紹了SpringBoot實現(xiàn)多數(shù)據(jù)源的切換,本文基于AOP來實現(xiàn)數(shù)據(jù)源的切換,文中通過示例代碼介紹的非常詳細,感興趣的小伙伴們可以參考一下
    2022-03-03
  • springboot mybatis手動事務的實現(xiàn)

    springboot mybatis手動事務的實現(xiàn)

    本文主要介紹了springboot mybatis手動事務的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-12-12
  • Spring @Configuration注解及配置方法

    Spring @Configuration注解及配置方法

    這篇文章主要介紹了Spring @Configuration注解及配置方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-04-04
  • Java?9?中的模塊Module系統(tǒng)

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

    Java?9?引入的模塊是在Java包(package)的基礎上又引入的一個新的抽象層,基于package這一點很重要,這里需要強調(diào)一下,接下來通過本文給大家介紹Java?9?中的模塊Module系統(tǒng),感興趣的朋友一起看看吧
    2022-03-03
  • Java中基于maven實現(xiàn)zxing二維碼功能

    Java中基于maven實現(xiàn)zxing二維碼功能

    這篇文章主要介紹了Java中基于maven實現(xiàn)zxing二維碼功能,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2017-02-02
  • 詳解Spring Boot 異步執(zhí)行方法

    詳解Spring Boot 異步執(zhí)行方法

    這篇文章主要介紹了Spring Boot 異步執(zhí)行方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-03-03
  • shiro整合springboot前后端分離

    shiro整合springboot前后端分離

    這篇文章主要介紹了shiro整合springboot前后端分離,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • IntelliJ IDEA中Project與Module的概念以及區(qū)別

    IntelliJ IDEA中Project與Module的概念以及區(qū)別

    這篇文章主要給大家介紹了關于IntelliJ IDEA中Project與Module的概念以及區(qū)別的相關資料,文中通過實例介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-01-01

最新評論

佛学| 共和县| 邓州市| 沁水县| 达尔| 巫溪县| 措勤县| 常宁市| 五常市| 南江县| 锡林郭勒盟| 航空| 民丰县| 封开县| 楚雄市| 紫云| 吉安市| 申扎县| 舞钢市| 贡觉县| 南投县| 民和| 开封县| 惠来县| 峨边| 襄垣县| 工布江达县| 黎川县| 阜南县| 北票市| 克拉玛依市| 西乌珠穆沁旗| 密云县| 乌鲁木齐县| 保定市| 河东区| 黎平县| 富宁县| 峡江县| 澄城县| 伊金霍洛旗|