天天看點

這樣終止線程,竟然會導緻服務當機?

在開始之前,我們先來看以下代碼會有什麼問題?

或許你已經發現了,上面這段代碼使用了 <code>Thread.stop()</code> 來終止線程,在 Java 程式中是不允許這樣終止線程的。什麼?你問為什麼不能這樣?

首先來說 IDE 都會鄙視你了,它會阻止你使用 <code>Thread.stop()</code> !

什麼?你不信。那麼來看這張圖:

好吧,那為什麼不能這樣用呢?總得給我一個敷衍的理由吧?

其實是這樣的,以文章剛開頭的那段代碼來說,它的執行結果是:

子線程開始執行 主線程執行完成

我們發現了一個驚天的大問題,最重要的那段僞代碼竟然沒執行,如下圖所示:

可以看出使用 <code>stop()</code> 終止線程之後,線程剩餘的部分代碼會放棄執行,這樣會造成嚴重的且不易被發現的驚天大 Bug,假如沒有執行的那段代碼是釋放系統資源的代碼,或者是此程式的主要邏輯處理代碼。這就破壞了程式基本邏輯的完整性,導緻意想不到的問題發生,而且它還很隐秘,不易被發現和修複。

有人說,這還不簡單,我加個 <code>finally</code> 不就完了嗎?

這???杠精哪都有,今年特别多。

行,既然這個說服不了你,咱接着往下看。

我們知道在 Java 中 <code>synchronized</code> 屬于獨占式可重入悲觀鎖,如果我們使用它修飾代碼,妥妥的多線程沒問題,但如果碰到 <code>stop()</code> 方法就不一定了,直接來看代碼吧。

以上程式的執行結果為:

Thread-5 | num=1 Thread-4 | num=1 Thread-2 | num=1 Thread-1 | num=1 Thread-8 | num=1 Thread-6 | num=1 Thread-9 | num=1 Thread-3 | num=1 Thread-7 | num=1 Thread-10 | num=1

從結果可以看出,以上代碼經過 <code>synchronized</code> 修飾的 ++ 和 -- 操作,到最後列印的結果 num 竟然不是 0,而是 1。

這是因為 <code>stop()</code> 方法會釋放此線程中的所有鎖,導緻程式執行紊亂,破壞了程式的原子操作邏輯。

以上的這些問題,導緻了 JDK 廢棄了 <code>stop()</code> 的方法,它的廢棄源碼如下:

可以看出 <code>stop()</code> 方法被 <code>@Deprecated</code> 注釋修飾了,而被此注解修飾的代碼表示為過時方法,不建議被使用。從 <code>stop()</code> 的備注資訊可以看出,官方也不建議使用 <code>stop()</code> ,說它是一個非安全的方法。

那如何終止線程呢?這裡提供 2 個正确的方法:

設定退出辨別退出線程;

使用 <code>interrupt()</code> 方法終止線程。

我們可以自定義一個布爾變量來辨別是否需要退出線程,實作代碼如下:

可以看出我們使用了關鍵字 <code>volatile</code> 對線程進行了修飾,這樣就可以保證多線程的執行安全了,在我們需要讓線程退出時,隻需要把變量 <code>exit</code> 指派為 <code>true</code> 就可以了。

當我們使用 <code>interrupt()</code> 方法時,以上兩個示例的執行結果就正常了,執行代碼如下:

子線程的重要業務方法 sleep interrupted Thread-1 | num=0 Thread-9 | num=0 Thread-10 | num=0 Thread-7 | num=0 Thread-6 | num=0 Thread-5 | num=0 Thread-4 | num=0 Thread-2 | num=0 Thread-3 | num=0 Thread-11 | num=0 Thread-8 | num=0

可以看出以上的執行都符合我們的預期,這才是正确的終止線程的方式。

本文我們講了線程的三種終止方式,自定義退出辨別的方式、使用 <code>stop()</code> 的方式或 <code>interrupt()</code> 的方式。其中 <code>stop()</code> 的方式會導緻程式的完整性和原子性被破壞的問題,并且此方法被 JDK 辨別為過期方法,不建議使用,而 <code>interrupt()</code> 方法無疑是最适合我們的終止線程的方式。

關注下面二維碼,訂閱更多精彩内容。

這樣終止線程,竟然會導緻服務當機?
這樣終止線程,竟然會導緻服務當機?
這樣終止線程,竟然會導緻服務當機?

關注公衆号(加好友):

這樣終止線程,竟然會導緻服務當機?

作者:

王磊的部落格

出處:

http://vipstone.cnblogs.com/