協作,才能更好的中斷線程

来源:https://www.cnblogs.com/goodAndyxublog/archive/2019/10/09/11644252.html
-Advertisement-
Play Games

聊起中斷,大家可能最熟悉的例子就是線程休眠。下麵就是一個線程休眠的 demo,在這個例子中,當我們調用 方法,該方法將會拋出一個需要捕獲的中斷異常,這裡捕獲該異常並直接返回。 java for (int i = 0; i An interrupt is an indication to a thre ...


聊起中斷,大家可能最熟悉的例子就是線程休眠。下麵就是一個線程休眠的 demo,在這個例子中,當我們調用 sleep 方法,該方法將會拋出一個需要捕獲的中斷異常,這裡捕獲該異常並直接返回。

        for (int i = 0; i < somethings.size(); i++) {
            // 休眠 4 s
            try {
                Thread.sleep(4000);
            } catch (InterruptedException e) {
                // 拋出中斷異常
                return;
            }
            // 輸出
            System.out.println(somethings.get(i));
        }

除了 InterruptedException 中斷異常,另外還有三個中斷相關的方法,三個方法都與線程相關。

  • thread#interrupt
  • Thread#interrupted
  • thread#isInterrupted

interrupt 方法用於中斷線程,但是並不是說該方法就能直接使線程停止

下麵使用 interrupt 中斷線程,這裡我們期望中斷直接停止子線程輸出。但是當主線程調用子線程 interrupt 方法,子線程並卻沒有被終止,還在繼續列印數字。

        Runnable interruptedTask=new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i <Integer.MAX_VALUE ; i++) {
                    System.out.println(i);
                }
            }
        };

        Thread interruptThread=new Thread(interruptedTask);
        interruptThread.start();
        // 休眠 5 s,
        TimeUnit.SECONDS.sleep(2);
        // 中斷當前線程
        interruptThread.interrupt();
        // 再次休眠,觀察子線程
        TimeUnit.SECONDS.sleep(2);

引用 Java 官方對於中斷的解釋:

An interrupt is an indication to a thread that it should stop what it is doing and do something else. It's up to the programmer to decide exactly how a thread responds to an interrupt, but it is very common for the thread to terminate

中斷僅僅只是表明這個線程可以停止,但是線程是否停止完全取決於線程自己。只有線程相互協作,才能更好的停止線程。

每個線程都包含一個內部標誌,用來表示中斷狀態。調用線程的 interrupt 方法將會設置該狀態位,對於 Thread#sleep 等阻塞方法,將會拋出 InterruptedException ,並清除中斷標誌。

我們可以使用 thread#isInterruptedThread#interrupted 檢查中斷狀態。但是需要註意,兩個方法存在一些區別,Thread#interrupted 為靜態類方法,該方法檢測到中斷之後就會清除中斷標誌。

上面的方法我們只要加上中斷狀態判斷就也可以停止線程。

        Runnable interruptedTask=new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i <Integer.MAX_VALUE ; i++) {
                    // 一旦檢測到中斷標誌,停止線程
                    if(Thread.interrupted()){
                        System.out.println("interrupted!!!!");
                        break;
                    }
                    System.out.println(i);
                }
            }
        };

        Thread interruptThread=new Thread(interruptedTask);
        interruptThread.start();
        // 休眠 5 s,
        TimeUnit.SECONDS.sleep(2);
        // 中斷當前線程
        interruptThread.interrupt();
        // 再次休眠,觀察子線程
        TimeUnit.SECONDS.sleep(2);
    }

中斷最佳實踐

不要隨意『吃掉』中斷異常

由於中斷異常是一個 checked exception,我們不得不需要處理該異常。如果我們可以保證該異常不影響應用,我們可以直接『吃掉』這個異常。其他情況下我們需要正確處理這個異常。

最簡單的做法就是不處理該異常,直接向上拋出中斷異常,讓上層調用者決定如何處理。

但是有些情況下,卻不適合上面的做法,這種情況下我們需要在 catch 中處理中斷。如果實在不知道如何處理,那就是記錄該異常,並使用日誌方式輸出。


中斷不會停止阻塞 IO

上面我們說到,對於一些阻塞方法如 Thread#sleep ,將會拋出中斷異常。但是對於 Socket 等阻塞 IO 調用,並不會拋出這個異常。也就是說中斷並不會停止阻塞 IO 的調用。

這是因為當調用 Thread#sleep 等阻塞方法時,Java 線程狀態將會從 RUNNABLE 轉變為 TIMED_WAITINGWATTING。而當線程阻塞在 IO 讀取時,Java 線程實際狀態卻還是 RUNNABLE。如果你對這個線程狀態還有疑惑,可以閱讀下這篇文章 面試官:都說阻塞 I/O 模型將會使線程休眠,為什麼 Java 線程狀態卻是 RUNNABLE?,深入理解一下線程狀態。

本文首發於studyidea.cn

歡迎關註我的公眾號:程式通事,獲得日常乾貨推送。如果您對我的專題內容感興趣,也可以關註我的博客:studyidea.cn

其他平臺.png


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前言 說真的,平常看源碼都是自己看完自己懂,很少有寫出來的衝動。 但是在寫演算法的時候,經常用到java中各種集合,其中也比較常用到remove方法。 remove有重載函數,分別傳入參數是索引index或者數據Object(指定泛型後自動轉換),如果指定泛型是其他數據類型還好,但是指定的是Integ ...
  • 前些天幫一個朋友做網站,全站都是靜態頁面,唯一需要用到後端開發的是他需要一個留言板。傳統的留言板一般都是提交後保存到資料庫,然後提供一個後臺的留言列表給管理人員看,我嫌麻煩,就決定留言提交到後臺直接發郵件出去,這樣就不用開發後臺頁面了,他也不需要登錄一個什麼後臺才能看留言,兩全其美,豈不美哉。 1、 ...
  • 方法一:修改pom.xml文件 方法二:在Terminal執行命令 mvn install -DskipTests 方法三:在Terminal執行命令 mvn install -Dmaven.test.skip=true 轉載於:https://blog.csdn.net/so_geili/arti ...
  • 小文:今天面試又搞砸了? 小 k:怎麼了? 小文:又一個大小寫轉換的題目感覺答錯了。 小 k:說來聽聽。 小文:將"hello world"轉換為首字母大寫"Hello World" 小 k:你的答案是什麼? 小文:用 capitalize 方法啊。 小 k:capitalize 方法只能將第一個單 ...
  • 本文主要講解Spring的基礎環境搭建以及演變由來,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 實驗環境:WIN7虛擬機 軟體:VC6 首先在VC6裡面寫一個空函數Fun(); F7編譯運行一下,沒有出錯,接著在函數處使用F9下斷點,使程式運行到Fun函數時停下。 接著F5開始運行這個程式 程式停在了Fun函數處,反彙編進去進行逆向分析 可以看到程式停在Fun函數的入口處,這裡的call就是F ...
  • 摘要 在 "詳解http報文" 一文中,詳細介紹了http報文的文本結構。那麼作為服務端,web容器是如何解析http報文的呢?本文以jetty和undertow容器為例,來解析web容器是如何處理http報文的。 在前文中我們從概覽中可以瞭解到,http報文其實就是一定規則的字元串,那麼解析它們, ...
  • composer是什麼 composer是PHP的插件依賴管理工具,我個人感覺和java的Maven、Gradle很類似。 Windows OS下安裝composer 參考: https://www.php.cn/php weizijiaocheng 400785.html https://blog ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...