interrupt(),interrupted() 和 isInterrupted() 的區別

不只Java發表於2019-02-28

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);
       }
   }
}
複製程式碼

輸出結果:

image

可以看出,子執行緒已經執行完成了。說明 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");
}
複製程式碼

輸出結果:

image

由此可以看出,執行緒並未停止,同時也證明了 interrupted() 方法的解釋:測試當前執行緒是否已經中斷,這個當前執行緒就是 main 執行緒,它從未中斷過,所以列印結果都是 false。

那麼如何使 main 執行緒產生中斷效果呢?將上面第 8 行程式碼註釋掉,並將第 7 行程式碼的註釋去掉再執行,我們就可以得到以下輸出結果:

image

從結果上看,方法 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");
}
複製程式碼

輸出結果:

image

結果很明顯,因為 isInterrupted() 不具有清除狀態標記功能,所以兩次都輸出 true。

參考文章:www.cnblogs.com/hapjin/p/54…

PS:本文原創釋出於微信公眾號「不只Java」。

interrupt(),interrupted() 和 isInterrupted() 的區別

相關文章