在之前的文章中 i-code.online -《併發程式設計-執行緒基礎》我們介紹了執行緒的建立和終止,從原始碼的角度去理解了其中的細節,那麼現在如果面試有人問你 「如何優雅的停止乙個執行緒?」, 你該如何去回答尼 ?能不能完美的回答尼?
這裡有個思考: 當處於sleep
時,執行緒能否感受到中斷訊號?
對於執行緒的停止,最優雅的方式就是通過interrupt
的方式來實現,關於他的詳細文章看之前文章即可,如interruptedexception
時,再次中斷設定,讓程式能後續繼續進行終止操作。不過對於interrupt
實現執行緒的終止在實際開發中發現使用的並不是很多,很多都可能喜歡另一種方式,通過標記位。
/** * @url: i-code.online * @author: zhoucx * @time: 2020/10/12 10:46 */public class producter implements runnable @override public void run() num++; } } catch (interruptedexception e) finally }}
首先,宣告了乙個生產者producer
,通過volatile
標記的初始值為true
的布林值mark
來停止執行緒。而在run()
方法中,while
的判斷語句是num
是否小於100000
及mark
是否被標記。while
迴圈體中判斷num
如果是 50 的倍數就放到numqueue
倉庫中,numqueue
是生產者與消費者之間進行通訊的儲存器,當num
大於100000
或被通知停止時,會跳出while
迴圈並執行finally
語句塊,告訴大家「生產者執行結束」
/** * @url: i-code.online * @author: zhoucx * @time: 2020/10/12 11:03 */public class consumer implements runnable @override public void run() } catch (interruptedexception e) finally }}
而對於消費者consumer
,它與生產者共用同乙個倉庫numqueue
,在run()
方法中我們通過判斷隨機數大小來確定是否要繼續消費,剛才生產者生產了一些 50 的倍數供消費者使用,消費者是否繼續使用數字的判斷條件是產生乙個隨機數並與 0.97 進行比較,大於 0.97 就不再繼續使用數字。
/** * @url: i-code.online * @author: zhoucx * @time: 2020/10/12 11:08 */public class mian }
主函式中很簡單,建立乙個 公共倉庫queue
長度為10,然後傳遞給兩個執行緒,然後啟動兩個執行緒,當我們啟動後要注意,我們的消費時有睡眠100
毫秒,那麼這個公共倉庫必然會被生產者裝滿進入阻塞,等待消費。
當消費者不再需要資料,就會將 canceled 的標記位設定為 true,理論上此時生產者會跳出 while 迴圈,並列印輸出「生產者執行結束」。
然而結果卻不是我們想象的那樣,儘管已經把producter.mark
設定成false
,但生產者仍然沒有停止,這是因為在這種情況下,生產者在執行numqueue.put(num)
時發生阻塞,在它被叫醒之前是沒有辦法進入下一次迴圈判斷producter.mark
的值的,所以在這種情況下用volatile
是沒有辦法讓生產者停下來的,相反如果用interrupt
語句來中斷,即使生產者處於阻塞狀態,仍然能夠感受到中斷訊號,並做響應處理。
通過上面的介紹我們知道了,執行緒終止的主要兩種方式,一種是 `interrupt` 一種是`volatile` ,兩種類似的地方都是通過標記來實現的,不過`interrupt` 是中斷訊號傳遞,基於系統層次的,不受阻塞影響,而對於 `volatile` ,我們是利用其可見性而頂乙個標記位標量,但是當出現阻塞等時無法進行及時的通知。
在我們平時的開發中,我們視情況而定,並不是說必須使用 `interrupt` ,在一般情況下都是可以使用 `volatile` 的,但是這需要我們精確的掌握其中的場景。
如何優雅的停止乙個執行緒
首先我們先了解下,執行緒是分為使用者執行緒和守護執行緒的,他們的區別就在 使用者執行緒當我們的主線程停止後,使用者執行緒不會隨著主線程停止。守護執行緒當我們的主線程停止後,會跟隨著主線程一起停止。一般我們建立的都是使用者執行緒,那守護執行緒有哪些呢,例如跟程式一起啟動的gc執行緒就是守護執行緒。停止...
如何停止乙個執行緒
停止乙個執行緒的最佳方法是讓它執行完畢,沒有辦法立即停止乙個執行緒,但你可以控制何時或什麼條件下讓他執行完畢。通過條件變數控制線程的執行,執行緒內部檢查變數狀態,外部改變變數值可控制停止執行。為保證執行緒間的即時通訊,需要使用volatile關鍵字或鎖,確保讀執行緒與寫執行緒變數狀態的一致性。pub...
優雅的停止執行緒
thread類的start 方法啟動多執行緒,thread原本也有提供有停止方法stop 但從1.2開始已經廢除了,因為這種方法可能造成執行緒的死鎖,現在實現執行緒的停止需要通過一種柔和的方式進行。範例 實現執行緒柔和的停止 package multithreading public class s...