什么是線程:對於現在的計算機而言,一般都是多核處理器;對於一個程序而言,在宏觀上來說可以同時執行多個任務;那么每一個任務可以稱之為一個線程,而每一個程序可以稱之為一個進程;並發執行的進程數目並不是由CPU的數目決定的,操作系統將CPU的時間片分配給每一個進程,在宏觀上來說給人一種並行處理的感覺;線程和進程最大的區別就是每一個進程擁有自己獨享的變量,而線程之間卻是共享變量,盡管多線程共享變量會帶來種種並發安全問題,但是Java程序對於線程安全問題的處理已經很完善了。
在講述線程的中斷狀態之前,我們先來看一看JDK中對於線程的狀態做了哪一些的定義:
public enum State { /** * 線程的新建狀態,線程沒有開始運行 */ NEW, /** * 線程的可運行狀態,該狀態表示可以在JVM中運行但同時也有可能等待來自操作系統對其他資源的處理 */ RUNNABLE, /** * 線程的阻塞狀態,該狀態下的線程正在等待同步鎖,試圖進入同步方法或者同步代碼塊或者重入鎖的同步方法或者代碼塊 */ BLOCKED, /** * 線程的等待狀態,該狀態的下的線程同樣會一直等待下去,直到有其他線程將其喚醒,否則會陷入一直的等待狀態 */ WAITING, /** * 線程的計時等待狀態,當時間到了之后並不能進入可運行狀態,只是有機會獲取對象的鎖 */ TIMED_WAITING, /** * 線程的終止狀態 */ TERMINATED; }
接下來我們看看三個方法:
1 boolean isInterrupted();表示判斷該線程是否處於中斷位;如果處於中斷位置,返回true,否則返回false;默認情況下處於非中斷位,返回false;(源碼如下)
public boolean isInterrupted() { return this.isInterrupted(false); } private native boolean isInterrupted(boolean var1);
2 void interrupt();將當前線程的中斷位進行標記;表示該線程的中斷位置為true;
public void interrupt() { if (this != Thread.currentThread()) checkAccess(); synchronized (blockerLock) { Interruptible b = blocker; if (b != null) { interrupt0(); // 僅僅將當前線程的中斷位進行標記
b.interrupt(this); return; } } interrupt0(); }
3 static boolean interrupted();調用該方法,就會清除線程的中斷狀態
public static boolean interrupted() { return currentThread().isInterrupted(true); }
看一段代碼的實例:
package com.temps.service.impl; /** * @Authgor: gosaint * @Description: * @Date Created in 11:04 2018/5/30 * @Modified By: */
public class ThreadTest extends Thread{ @Override public void run() { System.out.println("Test Thread!"); } public static void main(String[] args) { Thread t=new ThreadTest(); /** * 獲取線程的狀態 */ System.out.println("線程的狀態為"+t.getState()); /** 中斷線程*/ t.interrupt(); System.out.println(t.isInterrupted()); } }
上述代碼我們創建了一個線程,但是並沒有啟動該線程;理論上來說該線程處於新建狀態;調用了interrupt()方法之后,會出現什么情況;
結果就是線程的中斷標志位是false;不會發生任何的變化;在《java core》中說:沒有任何語言方面的需求要求一個中斷的線程被終止;照這樣說來,線程的終止狀態即使調用了interrupt()方法,本身也不會發生任何的變化;同樣的新建狀態也不會發生任何的變化!
下面的程序創建並啟動了一個新的線程,然后調用join()方法,讓該線程執行完畢,此時調用interrupt()方法,顯示的結果如下所示:

package com.temps.service.impl; /** * @Authgor: gosaint * @Description: * @Date Created in 11:04 2018/5/30 * @Modified By: */
public class ThreadTest extends Thread{ @Override public void run() { System.out.println("Test Thread!"); } public static void main(String[] args) { Thread t=new ThreadTest(); t.start(); try { t.join(); System.out.println("線程的狀態為"+t.getState()); /** 中斷線程*/ t.interrupt(); System.out.println(t.isInterrupted()); } catch (InterruptedException e) { e.printStackTrace(); } } }
如果線程處於運行狀態,那么該線程的狀態就是RUNNABLE,但是不一定所有處於RUNNABLE狀態的線程都能獲得CPU運行,在某個時間段,只能由一個線程占用CPU,那么其余的線程雖然狀態是RUNNABLE,但是都沒有處於運行狀態。而我們處於RUNNABLE狀態的線程在遭遇中斷操作的時候只會設置該線程的中斷標志位,並不會讓線程實際中斷,想要發現本線程已經被要求中斷了則需要用程序去判斷。例如:
package com.temps.service.impl; /** * @Authgor: gosaint * @Description: * @Date Created in 11:04 2018/5/30 * @Modified By: */
public class ThreadTest extends Thread{ @Override public void run() { while (true){ //System.out.println("Test Thread---------!");
} } public static void main(String[] args) { Thread t=new ThreadTest(); t.start(); try { System.out.println("線程的狀態為"+t.getState()); /** 中斷線程*/ t.interrupt(); Thread.sleep(1000);//等待線程中斷完畢
System.out.println(t.isInterrupted()); System.out.println("線程的狀態為end="+t.getState()); } catch (Exception e) { e.printStackTrace(); } } }

盡管調用interrupt()方法並不能中斷線程的執行,但是在可運行狀態下的線程可以改變線程的中斷位標志,此時我們可以用自己的代碼來控制,比如說
if(Thread.currentThread.isInterrupt()==true){ //退出JVM
}
對於線程的阻塞狀態和線程的可運行狀態基本是相同的;
package com.temps.service.impl; /** * @Authgor: gosaint * @Description: * @Date Created in 11:04 2018/5/30 * @Modified By: */
public class ThreadTest extends Thread{ @Override public void run() { doSomething(); } public synchronized static void doSomething(){ while(true){ //do something
} } public static void main(String[] args) throws Exception{ Thread t1=new ThreadTest(); t1.start(); Thread t2=new ThreadTest(); t2.start(); Thread.sleep(1000); System.out.println(t1.getState()); System.out.println(t2.getState()); System.out.println("0000000000000000000"); t2.interrupt(); System.out.println(t2.isInterrupted()); System.out.println(t2.getState()); } }

創建了兩個線程,並且按照順序啟動;在run() 方法中調用了同步方法,並且是死循環的狀態,此時調用的線程就會永久的持有同步鎖,那么其他的線程只能陷入無盡的等待鎖的狀態中,陷入阻塞狀態,調用結果很清楚的說明了這一點;

我們再來看看等待狀態和計時等待狀態的狀況:
package com.temps.service.impl; /** * @Authgor: gosaint * @Description: * @Date Created in 11:04 2018/5/30 * @Modified By: */
public class ThreadTest extends Thread{ @Override public void run() { synchronized (this){ try { wait(); } catch (InterruptedException e) { System.out.println("線程中斷異常!"); } } } public static void main(String[] args) throws Exception{ Thread t1=new ThreadTest(); t1.start(); Thread.sleep(5000); System.out.println(t1.getState()); t1.interrupt(); Thread.sleep(1000); System.out.println(t1.isInterrupted()); } }
創建一個線程,然后啟動線程,在run()方法中進入等待狀態;之后再調用interrupt()方法,檢測中斷狀態

綜上所述,我們分別介紹了不同種線程的不同狀態下對於中斷請求的反應。NEW和TERMINATED對於中斷操作幾乎是屏蔽的,RUNNABLE和BLOCKED類似,對於中斷操作只是設置中斷標志位並沒有強制終止線程,對於線程的終止權利依然在程序手中。WAITING/TIMED_WAITING狀態下的線程對於中斷操作是敏感的,他們會拋出異常並清空中斷標志位。