【多執行緒】Thread.interrupted()與thread.isInterrupted()的區別
在Java的執行緒基本操作方法中,有兩種方式獲取當前執行緒的isInterrupt屬性。一種是物件方法thread.isInterrupted(),另一種是Thread類的靜態方法Thread.interrupted()。這兩個方法看似相同,實際上是有區別的,我們來看看Java的Thread類的這部分原始碼:
public class Thread implements Runnable { ...... public static boolean interrupted() { return currentThread().isInterrupted(true); } public boolean isInterrupted() { return isInterrupted(false); } /** * Tests if some Thread has been interrupted. The interrupted state * is reset or not based on the value of ClearInterrupted that is * passed. */ private native boolean isInterrupted(boolean ClearInterrupted); ...... }
可以看到,物件方法的thread.isInterrupted()和靜態方法的Thread.interrupted()都是呼叫的JNI底層的isInterrupted()方法。但是區別在於這個ClearInterrupted引數,前者傳入的false,後者傳入的是true。相信各位讀者都已經猜出其中的含義了,ClearInterrupted引數向作業系統層指明是否在獲取狀態後將當前執行緒的isInterrupt屬性重置為(或者叫恢復,或者叫清除)false。
這就意味著當某個執行緒的isInterrupt屬性成功被置為true後,如果您使用物件方法thread.isInterrupted()獲取值,無論您獲取多少次得到的返回值都是true;但是如果您使用靜態方法Thread.interrupted()獲取值,那麼只有第一次獲取的結果是true,隨後執行緒的isInterrupt屬性將被恢復成false,後續無論使用Thread.interrupted()呼叫還是使用thread.isInterrupted()呼叫,獲取的結果都是false
=====================================================================
呼叫Thread.interrupt()方法並不能真正停止執行緒,只是在當前執行緒做了一箇中斷的狀態標誌。
public class MyThread extends Thread{ @Override public void run() { for (int i = 0; i < 100; i++) { super.run(); System.out.println("i="+(i+1)); } } }
public class Runner {
public static void main(String[] args) {
MyThread myThread = new MyThread();
myThread.start();
myThread.interrupt();
System.out.println("第一次呼叫myThread.isInterrupted(),返回值:"+myThread.isInterrupted());
System.out.println("第二次呼叫myThread.isInterrupted(),返回值:"+myThread.isInterrupted());
System.out.println("===========end=============");
}
}
上面我們建立了一個MyThread執行緒,然後Runner類中,執行main方法,建立MyThread的例項,啟動執行緒,然後呼叫myThread.interrupt(); 打印出資訊:
i=1 第一次呼叫myThread.isInterrupted(),返回值:true i=2 第二次呼叫myThread.isInterrupted(),返回值:true i=3 ==========end============== i=4 i=5 i=6 i=7 i=8 i=9 i=10 i=11 i=12 i=13 i=14
從列印資訊可以看出,雖然呼叫了myThread.interrupt()方法,但是MyThread並沒有立即中斷執行。這裡我們兩次呼叫myThread.isInterrupted(),返回值都是true。 我們對Runner方法坐下修改,改成兩次呼叫myThread.interrupted()。 程式碼如下:
public class Runner {
public static void main(String[] args) {
MyThread myThread = new MyThread();
myThread.start();
myThread.interrupt();
System.out.println("第一次呼叫myThread.interrupted(),返回值:"+myThread.interrupted());
System.out.println("第二次呼叫myThread.interrupted(),返回值:"+myThread.interrupted());
System.out.println("============end===================");
}
}
列印資訊如下:
第一次呼叫myThread.interrupted(),返回值:false i=1 第二次呼叫myThread.interrupted(),返回值:false i=2 ===========end================= i=3 i=4 i=5 i=6
雖然執行緒依然沒有被中斷,但是呼叫myThread.interrupted()是,返回都是false。難度是MyThread並沒有中斷狀態嗎?
再看一下程式碼:
public class Runner {
public static void main(String[] args) {
Thread.currentThread().interrupt();
System.out.println("第一次呼叫Thread.interrupted(),返回值:"+Thread.interrupted());
System.out.println("第二次呼叫Thread.interrupted(),返回值:"+Thread.interrupted());
System.out.println("=================end===============================");
}
}
列印資訊如下:
第一次呼叫Thread.interrupted(),返回值:true 第二次呼叫Thread.interrupted(),返回值:false ========end=======
以上程式碼是對當前執行緒,即main方法執行的執行緒,呼叫interrunt方法。第一次呼叫Thread.interrupted()返回值是true,說明當前執行緒已經被標記了中斷狀態,那麼為什麼第二次呼叫Thread.interrupted()返回值卻是false呢?
這裡需要引出官方文件對Thread.interrupted()的定義:
測試當前執行緒是否已經中斷,執行緒的中斷狀態也是由該方法清除。
也就是說,如果連續兩次呼叫該方法,那麼第一次呼叫時,如果當前執行緒已經處於中斷狀態,那麼該方法會返回true,同時清除當前執行緒被標記的中斷狀態。第二次呼叫時,(第二次呼叫之前,沒有再次呼叫Thread.currentThread().interrupt();)就會返回false了。
總結
- 呼叫執行緒的interrupt方法,並不能真正中斷執行緒,只是給執行緒做了中斷狀態的標誌
- Thread.interrupted():測試當前執行緒是否處於中斷狀態。執行後將中斷狀態標誌為false
- Thread.isInterrupte(): 測試執行緒Thread物件是否已經處於中斷狀態。但不具有清除功能