本節書摘來自華章社群《java多線程程式設計核心技術》一書中的第1章,第1.7節停止線程,作者高洪岩,更多章節内容可以通路雲栖社群“華章社群”公衆号檢視
1.7 停止線程
停止線程是在多線程開發時很重要的技術點,掌握此技術可以對線程的停止進行有效的處理。停止線程在java語言中并不像break語句那樣幹脆,需要一些技巧性的處理。
使用java内置支援多線程的類設計多線程應用是很常見的事情,然而,多線程給開發人員帶來了一些新的挑戰,如果處理不好就會導緻超出預期的行為并且難以定位錯誤。
本節将讨論如何更好地停止一個線程。停止一個線程意味着線上程處理完任務之前停掉正在做的操作,也就是放棄目前的操作。雖然這看起來非常簡單,但是必須做好防範措施,以便達到預期的效果。停止一個線程可以使用thread.stop()方法,但最好不用它。雖然它确實可以停止一個正在運作的線程,但是這個方法是不安全的(unsafe),而且是已被棄用廢棄的(deprecated),在将來的java版本中,這個方法将不可用或不被支援。
大多數停止一個線程的操作使用thread.interrupt()方法,盡管方法的名稱是“停止,中止”的意思,但這個方法不會終止一個正在運作的線程,還需要加入一個判斷才可以完成線程的停止。關于此知識點在後面有專門的章節進行介紹。
在java中有以下3種方法可以終止正在運作的線程:
1)使用退出标志,使線程正常退出,也就是當run方法完成後線程終止。
2)使用stop方法強行終止線程,但是不推薦使用這個方法,因為stop和suspend及resume一樣,都是廢棄過期的方法,使用它們可能産生不可預料的結果。
3)使用interrupt方法中斷線程。
這3種方法都會在後面的章節進行介紹。
1.7.1 停止不了的線程
本示例将調用interrupt()方法來停止線程,但interrupt()方法的使用效果并不像for+break語句那樣,馬上就停止循環。調用interrupt()方法僅僅是在目前線程中打了一個停止的标記,并不是真的停止線程。
建立名稱為t11的項目,檔案mythread.java代碼如下:
程式運作結果如圖1-28所示。
把eclipse軟體中的控制台的日志複制到editplus軟體中,确認一下日志是否是50萬行,效果如圖1-29所示。

從運作的結果來看,調用interrupt方法并沒有停止線程。如何停止線程呢?
1.7.2 判斷線程是否是停止狀态
在介紹如何停止線程的知識點前,先來看一下如何判斷線程的狀态是不是停止的。在java的sdk中,thread.java類裡提供了兩種方法。
1)this.interrupted():測試目前線程是否已經中斷。
2)this.isinterrupted():測試線程是否已經中斷。
interrupted()方法的聲明如圖1-30所示。
isinterrupted ()方法的聲明如圖1-31所示。
那麼這兩個方法有什麼差別呢?先來看看this.interrupted()方法的解釋:測試目前線程是否已經中斷,目前線程是指運作this.interrupted()方法的線程。為了對此方法有更深入的了解,建立項目,名稱為t12,類mythread.java代碼如下:
程式運作後的結果如圖1-32所示。
類run.java中雖然是在thread對象上調用以下代碼:
thread.interrupt();
來停止thread對象所代表的線程,在後面又使用以下代碼:
system.out.println("是否停止1?="+thread.interrupted());
system.out.println("是否停止2?="+thread.interrupted());
來判斷thread對象所代表的線程是否停止,但從控制台列印的結果來看,線程并未停止,這也就證明了interrupted()方法的解釋:測試目前線程是否已經中斷。這個“目前線程”是main,它從未中斷過,是以列印的結果是兩個false。
如何使main線程産生中斷效果呢?建立run2.java代碼如下:
程式運作後的效果如圖1-33所示。
從上述的結果來看,方法interrupted()的确判斷出目前線程是否是停止狀态。但為什麼第2個布爾值是false呢?檢視一下官方幫助文檔中對interrupted方法的解釋:
測試目前線程是否已經中斷。線程的中斷狀态由該方法清除。換句話說,如果連續兩次調用該方法,則第二次調用将傳回false(在第一次調用已清除了其中斷狀态之後,且第二次調用檢驗完中斷狀态前,目前線程再次中斷的情況除外)。
文檔已經解釋得很詳細,interrupted()方法具有清除狀态的功能,是以第2次調用interrupted()方法傳回的值是false。
介紹完interrupted()方法後再來看一下isinterrupted()方法,聲明如下:
public boolean isinterrupted()
從聲明中可以看出isinterrupted()方法不是static的。
繼續建立run3.java類,代碼如下:
程式運作結果如圖1-35所示。
上面的示例雖然停止了線程,但如果for語句下面還有語句,還是會繼續運作的。建立測試項目t13forprint,類mythread.java代碼如下:
package exthread;
public class mythread extends thread {
}
類run.java代碼如下:
package test;
import exthread.mythread;
public class run {
package testpackage;
檔案run.java代碼如下:
package test.run;
import testpackage.mythread;
public class synchronizedobject {
檔案mythread.java代碼如下:
import testpackage.synchronizedobject;
package extthread;
運作類run.java代碼如下:
import extthread.mythread;