1. 程式人生 > >協作,才能更好的中斷執行緒

協作,才能更好的中斷執行緒

聊起中斷,大家可能最熟悉的例子就是執行緒休眠。下面就是一個執行緒休眠的 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

相關推薦

協作才能中斷執行

聊起中斷,大家可能最熟悉的例子就是執行緒休眠。下面就是一個執行緒休眠的 demo,在這個例子中,當我們呼叫 sleep 方法,該方法將會丟擲一個需要捕獲的中斷異常,這裡捕獲該異常並直接返回。 for (int i = 0; i < somethings.size(); i++) {

擁抱Android開發的變化才能的擁抱未來!

近期很多同學都問過我這樣的問題。 “現在學習Android開發還有前景嗎?” “Android開發還有什麼可以研究的?” 大家對於職業的未來,都有一些迷茫和焦慮,為什麼會這樣呢? 現在網際網路行業,各大公司已經從爭奪使用者轉為爭奪使用者時長。而小程式、快應用的崛起,也讓許多 App

先照顧自己才能的去照顧別人

   其實大城市裡打拼吧,真的是不容易。曾經我也幻想過,要是哪天深夜,我突然發高燒,站不起來也喊不出來,死了都沒人知道,想想都好可怕....... 事實證明,想多了,因為我百毒不侵啊。   無數次敲著程式碼的時候,會胸悶啊。然後趕緊喝口水,站起來向遠方眺望下,或者就是存粹的站起來站兩分鐘。。   還有幾次吃晚

一、多執行基礎概念、實現執行三種方法、中斷執行方法以及執行狀態轉化

1、CPU核心數和執行緒數的關係 1:1的關係,引入超執行緒之後,就是1:2 2、cpu時間輪轉機制,即RR排程 3、程序和執行緒 程序:程式執行資源分配最小單位,程序內部有多個執行緒,多個執行緒之間會共享程序資源 執行緒:CPU排程的最小單位 4、並行和併發

從身邊開源開始學習用過才能理解程式碼

2015年12月20日,雲棲社群上線。2018年12月20日,雲棲社群3歲。 阿里巴巴常說“晴天修屋頂”。 在我們看來,寒冬中,最值得投資的是學習,是增厚的知識儲備。 所以社群特別製作了這個專輯——分享給開發者們20個彌足珍貴的成長感悟,50本書單。 多年以後,再回首2018-19年,留給我們自己的,

雲棲專輯 | 阿里開發者們的第3個感悟:從身邊開源開始學習用過才能理解程式碼

2015年12月20日,雲棲社群上線。2018年12月20日,雲棲社群3歲。 阿里巴巴常說“晴天修屋頂”。 在我們看來,寒冬中,最值得投資的是學習,是增厚的知識儲備。 所以社群特別製作了這個專輯——分享給開發者們20個彌足珍貴的成長感悟,50本書單。 多年以後,再回首2018-19年,留給我們自

MQTT是IBM開發的一個即時通訊協議構建於TCP/IP協議上是物聯網IoT的訂閱協議借助消息推送功能可以地實現遠程控制

集合 cap 消息處理 簡易 遠程控制 mes ogr 設計思想 成本 最近一直做物聯網方面的開發,以下內容關於使用MQTT過程中遇到問題的記錄以及需要掌握的機制原理,主要講解理論。 背景 MQTT是IBM開發的一個即時通訊協議。MQTT構建於TCP/IP協議上

當我們需要部署微服務的時候哪個

hit 額外 應用生命周期 更多 .html 服務架構 功能 ros 缺點 當我們需要部署微服務的時候,哪個更好?Spring Cloud還是Kubernetes?答案是都可以,只是各自有其優勢。 Spring Cloud 和 Kubernetes 都宣稱自己是開發和運行微

ResNeXt——與 ResNet 相比相同的參數個數結果:一個 101 層的 ResNeXt 網絡和 200 層的 ResNet 準確度差不多但是計算量只有後者的一半

模式 這樣的 cap dfa 不同 dual 重復 ORC 但是 from:https://blog.csdn.net/xuanwu_yan/article/details/53455260 背景 論文地址:Aggregated Residual Transformati

QoS最佳實踐實現的帶寬管理

哪些 重新 開發 鏈路 定義 設備 中標 處理 服務 服務質量(QoS)使管理員能夠在通過公司網絡時確定某些數據流量的優先級。但是為了使QoS工作,必須首先進行大量的規劃和協調。如果你的網絡遇到帶寬和延遲問題,請確保遵循這些最佳實踐指南,以便使用QoS技術實現更好的帶寬管理

呼叫Spring所管理的bean的方法時候為何不會出現執行安全問題?

首先jvm會在記憶體中開闢一塊儲存空間做為執行緒棧空間,每個執行緒都有自己的棧(後進先出)。 呼叫方法時,會在棧中壓入一個棧幀,用來儲存這個方法的引數和區域性變數; 方法返回時 ,棧幀就會彈出,方法的引數和區域性變數就會清除; 方法呼叫時,呼叫棧不斷處於漲落之中,如果呼叫的層級過深,

關於程序執行多程序和多執行的網路程式設計

程序執行緒網路 多工程式設計 : 可以有效的利用計算機資源,同時執行多個任務 程序 : 程序就是程式在計算機中一次執行的過程 程序和程式的區別: 程式是一個靜態檔案的描述,不佔計算機的系統資源 程序是一個動態的過程,佔有cpu記憶體等資源,有一定的生命週期 * 同一個程式的不同執行過程即為不同的程序

何愷明大神的「Focal Loss」如何地理解?

轉自:http://blog.csdn.net/c9Yv2cf9I06K2A9E/article/details/78920998   作者丨蘇劍林 單位丨廣州火焰資訊科技有限公司 研究方向丨NLP,神經網路 個人主頁丨kexue.fm   前言

jstack簡單使用定位死迴圈、執行阻塞、死鎖等問題

當我們執行java程式時,發現程式不動,但又不知道是哪裡出問題時,可以使用JDK自帶的jstack工具去定位; 廢話不說,直接上例子吧,在window平臺上的; 一、死迴圈 package software.architect.OtherAnalyzer.main; public

關於併發/並行阻塞/非阻塞同步/非同步及程序/執行的理解

1. 阻塞,非阻塞           一個執行緒/程序經歷的5個狀態,建立,就緒,執行,阻塞,終止。各個狀態的轉換條件如上圖,其中有個阻塞狀態,就是說當執行緒中呼叫某個函式,需要IO請求,或者暫時得不到競爭資源的,作業系統會把該執行緒

分清雲端儲存和雲備份才能理智的選擇“雲”

有關雲的炒作已經模糊了雲端儲存,以及雲備份恢復和還原(雲BURR)之間的界限。甚至使得雲端儲存和雲端的儲存,以及“同步和共享”這樣的概念差別變得模糊。許多供應商樂意與此,因為這使得他們的方案看上去對於潛在客戶更具吸引力。不過模糊不清的雲定義混淆了市場,妨礙了技術部署和推進的速度,並最終損害了市場中的

Web應用啟動時後臺自動啟動一個執行(轉)

原文:http://blog.sina.com.cn/s/blog_6810dfc20101ipzq.html Web應用啟動時,後臺自動啟動一個執行緒   (1)前言     前幾天,manager問道一個問題:能不能實現類似於cro

「阿里面試系列」面試加分項從JVM層面瞭解執行的啟動和停止

文章簡介 這一篇主要圍繞執行緒狀態控制相關的操作分析執行緒的原理,比如執行緒的中斷,執行緒的通訊等,內容比較多,可能會分兩篇文章 阿里面試系列導讀:關注我的技術公眾號【架構師修煉寶典】一週出產1-2篇技術文章。 【阿里面試系列】搞懂併發程式設計,輕鬆應對80%的面試場景 【阿里面試系列】

#Java多執行學習那麼如何實現多執行呢?

程序和執行緒的區別: 程序:每個程序都有獨立的程式碼和資料空間(程序上下文),程序間的切換會有較大的開銷,一個程序包含1–n個執行緒。 執行緒:同一類執行緒共享程式碼和資料空間,每個執行緒有獨立的執行棧和程式計數器(PC),執行緒切換開銷小。 執行緒和程序一樣分

linux定位應用問題的一些常用命令特別針對記憶體和執行分析的dump命令

1.jps找出程序號,找到對應的程序號後面才好繼續操作 2.linux檢視程序詳細資訊     ps -ef | grep 程序ID   3. dump記憶體資訊     Jmap -dump:format=b,file=YYMMddhhmm