1. 結論先行
interrupt():將呼叫該方法的物件所表示的執行緒標記一個停止標記,並不是真的停止該執行緒。
interrupted():獲取當前執行緒的中斷狀態,並且會清除執行緒的狀態標記。是一個是靜態方法。
isInterrupted():獲取呼叫該方法的物件所表示的執行緒,不會清除執行緒的狀態標記。是一個例項方法。
現在對各方法逐一進行具體介紹:
2. interrupt()
首先我們來使用一下 interrupt() 方法,觀察效果,程式碼如下:
public class MainTest {
@Test
public void test() {
try {
MyThread01 myThread = new MyThread01();
myThread.start();
myThread.sleep(2000);
myThread.interrupt();
} catch (Exception e) {
System.out.println("main catch");
e.printStackTrace();
}
}
}
public class MyThread01 extends Thread {
@Override
public void run() {
super.run();
for (int i = 0; i < 500; i++) {
System.out.println("i= " + i);
}
}
}
複製程式碼
輸出結果:
可以看出,子執行緒已經執行完成了。說明 interrupt() 方法是不能讓執行緒停止,和我們一開始所說的那樣,它僅僅是在當前執行緒記下一個停止標記而已。
那麼這個停止標記我們又怎麼知道呢?——此時就要介紹下面的 interrupted() 和 isInterrupted() 方法了。
3. interrupted() 和 isInterrupted()
-
interrupted() 方法的宣告為
public static boolean interrupted()
-
isInterrupted() 方法的宣告為
public boolean isInterrupted()
這兩個方法很相似,下面我們用程式來看下使用效果上的區別吧
先來看下使用 interrupted() 的程式。
@Test
public void test() {
try {
MyThread01 myThread = new MyThread01();
myThread.start();
myThread.sleep(1000);
// 7行: Thread.currentThread().interrupt(); // Thread.currentThread() 這裡表示 main 執行緒
myThread.interrupt();
// myThread.interrupted() 底層呼叫了 currentThread().isInterrupted(true); 作用是判斷當前執行緒是否為停止狀態
System.out.println("是否中斷1 " + myThread.interrupted());
System.out.println("是否中斷2 " + myThread.interrupted());
} catch (InterruptedException e) {
System.out.println("main catch");
}
System.out.println("main end");
}
複製程式碼
輸出結果:
由此可以看出,執行緒並未停止,同時也證明了 interrupted() 方法的解釋:測試當前執行緒是否已經中斷,這個當前執行緒就是 main 執行緒,它從未中斷過,所以列印結果都是 false。
那麼如何使 main 執行緒產生中斷效果呢?將上面第 8 行程式碼註釋掉,並將第 7 行程式碼的註釋去掉再執行,我們就可以得到以下輸出結果:
從結果上看,方法 interrupted() 的確判斷出了當前執行緒(此例為 main 執行緒)是否是停止狀態了,但為什麼第二個布林值為 false 呢?我們在最開始的時候有說過——interrupted() 測試當前執行緒是否已經是中斷狀態,執行後會將狀態標誌清除。
因為執行 interrupted() 後它會將狀態標誌清除,底層呼叫了 isInterrupted(true),此處引數為 true 。所以 interrupted() 具有清除狀態標記功能。
在第一次呼叫時,由於此前執行了 Thread.currentThread().interrupt()
;,導致當前執行緒被標記了一箇中斷標記,因此第一次呼叫 interrupted() 時返回 true。因為 interrupted() 具有清除狀態標記功能,所以在第二次呼叫 interrupted() 方法時會返回 false。
以上就是 interrupted() 的介紹內容,最後我們再來看下 isInterrupted() 方法吧。
isInterrupted() 和 interrupted() 有兩點不同:一是不具有清除狀態標記功能,因為底層傳入 isInterrupted() 方法的引數為 false。二是它判斷的執行緒呼叫該方法的物件所表示的執行緒,本例為 MyThread01 物件。
我們修改一下上面的程式碼,看下執行效果:
@Test
public void test() {
try {
MyThread01 myThread = new MyThread01();
myThread.start();
myThread.sleep(1000);
myThread.interrupt();
// 修改了下面這兩行。
// 上面的程式碼是 myThread.interrupted();
System.out.println("是否中斷1 " + myThread.isInterrupted());
System.out.println("是否中斷2 " + myThread.isInterrupted());
} catch (InterruptedException e) {
System.out.println("main catch");
e.printStackTrace();
}
System.out.println("main end");
}
複製程式碼
輸出結果:
結果很明顯,因為 isInterrupted() 不具有清除狀態標記功能,所以兩次都輸出 true。
參考文章:www.cnblogs.com/hapjin/p/54…
PS:本文原創釋出於微信公眾號「不只Java」。