首先看看官方說明:ide
interrupt()方法函數
其做用是中斷此線程(此線程不必定是當前線程,而是指調用該方法的Thread實例所表明的線程),但實際上只是給線程設置一箇中斷標誌,線程仍會繼續運行。測試
interrupted()方法this
做用是測試當前線程是否被中斷(檢查中斷標誌),返回一個boolean並清除中斷狀態,第二次再調用時中斷狀態已經被清除,將返回一個false。spa
isInterrupted()方法.net
做用是隻測試此線程是否被中斷 ,不清除中斷狀態線程
下面咱們進行測試說明:code
定義一個MyThread類,繼承Thread,以下:blog
public class MyThread extends Thread { @Override public void run() { for (int i = 0; i < 10; i++) { System.out.println("i="+(i+1)); } } }
在main方法中測試:繼承
public class Do { public static void main(String[] args ) { MyThread thread=new MyThread(); thread.start(); thread.interrupt(); System.out.println("第一次調用thread.isInterrupted():"+thread.isInterrupted()); System.out.println("第二次調用thread.isInterrupted():"+thread.isInterrupted()); System.out.println("thread是否存活:"+thread.isAlive()); } }
輸出以下:
從結果能夠看出調用interrupt()方法後,線程仍在繼續運行,並未中止,但已經給線程設置了中斷標誌,兩個isInterrupted()方法都會輸出true,也說明isInterrupted()方法並不會清除中斷狀態。
下面咱們把代碼修改一下,多加兩行調用interrupted()方法:
public class Do { public static void main(String[] args ) { MyThread thread=new MyThread(); thread.start(); thread.interrupt(); System.out.println("第一次調用thread.isInterrupted():"+thread.isInterrupted()); System.out.println("第二次調用thread.isInterrupted():"+thread.isInterrupted()); //測試interrupted()函數 System.out.println("第一次調用thread.interrupted():"+thread.interrupted()); System.out.println("第二次調用thread.interrupted():"+thread.interrupted()); System.out.println("thread是否存活:"+thread.isAlive()); } }
輸出以下:
從輸出結果看,可能會有疑惑,爲何後面兩個interrupted方法輸出的都是false,而不是預料中的一個true一個false?注意!!!這是一個坑!!!上面說到,interrupted()方法測試的是當前線程是否被中斷,當前線程!!!當前線程!!!,這裏當前線程是main線程,而thread.interrupt()中斷的是thread線程,這裏的此線程就是thread線程。因此當前線程main從未被中斷過,儘管interrupted()方法是以thread.interrupted()的形式被調用,但它檢測的仍然是main線程而不是檢測thread線程,因此thread.interrupted()在這裏至關於main.interrupted()。對於這點,下面咱們再修改進行測試。
Thread.currentThread()函數能夠獲取當前線程,下面代碼中獲取的是main線程
public class Do { public static void main(String[] args ) throws InterruptedException { Thread.currentThread().interrupt(); System.out.println("第一次調用Thread.currentThread().interrupt():" +Thread.currentThread().isInterrupted()); System.out.println("第一次調用thread.interrupted():" +Thread.currentThread().interrupted()); System.out.println("第二次調用thread.interrupted():" +Thread.currentThread().interrupted()); } }
這裏都是針對當前線程在操做,若是interrupted()方法有檢測中斷並清除中斷狀態的做用,預料中的輸出應該是true-true-false,實際輸出以下:
結果證實猜測是正確的。
若果想要是實現調用interrupt()方法真正的終止線程,則能夠在線程的run方法中作處理便可,好比直接跳出run()方法使線程結束,視具體狀況而定,下面是一個例子。
修改MyThread類:
public class MyThread extends Thread { @Override public void run() { for (int i = 0; i < 1000; i++) { System.out.println("i="+(i+1)); if(this.isInterrupted()){ System.out.println("經過this.isInterrupted()檢測到中斷"); System.out.println("第一個interrupted()"+this.interrupted()); System.out.println("第二個interrupted()"+this.interrupted()); break; } } System.out.println("由於檢測到中斷,因此跳出循環,線程到這裏結束,由於後面沒有內容了"); } }
測試MyThread:
public class Do { public static void main(String[] args ) throws InterruptedException { MyThread myThread=new MyThread(); myThread.start(); myThread.interrupt(); //sleep等待一秒,等myThread運行完 Thread.currentThread().sleep(1000); System.out.println("myThread線程是否存活:"+myThread.isAlive()); } }
結果:
總結:
關於這三個方法,interrupt()是給線程設置中斷標誌;
interrupted()是檢測中斷並清除中斷狀態;
isInterrupted()只檢測中斷。
還有重要的一點就是interrupted()做用於當前線程,interrupt()和isInterrupted()做用於此線程,即代碼中調用此方法的實例所表明的線程。
-------------------------------------------對線程中斷的理解-------------------------------------------
首先,一個線程不該該由其餘線程來強制中斷或中止,而是應該由線程本身自行中止。
因此,Thread.stop, Thread.suspend, Thread.resume 都已經被廢棄了。
而 Thread.interrupt 的做用其實也不是中斷線程,而是「通知線程應該中斷了」,
具體到底中斷仍是繼續運行,應該由被通知的線程本身處理。
具體來講,當對一個線程,調用 interrupt() 時,
① 若是線程處於被阻塞狀態(例如處於sleep, wait, join 等狀態),那麼線程將當即退出被阻塞狀態,並拋出一個InterruptedException異常。僅此而已。
② 若是線程處於正常活動狀態,那麼會將該線程的中斷標誌設置爲 true,僅此而已。被設置中斷標誌的線程將繼續正常運行,不受影響。
Thread thread = new Thread(() -> { while (!Thread.interrupted()) { // do more work. } }); thread.start(); // 一段時間之後 thread.interrupt();
例子:
public class Test { public static void main(String[] args) throws InterruptedException { // sleepThread睡眠1000ms final Thread sleepThread = new Thread() { @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } super.run(); } }; // busyThread一直執行死循環 Thread busyThread = new Thread() { @Override public void run() { while (true); } }; sleepThread.start(); busyThread.start(); sleepThread.interrupt(); // 改變中斷狀態標誌位 busyThread.interrupt(); System.out.println(busyThread.isInterrupted()); while (sleepThread.isInterrupted()); // 一直死循環等待該中斷標誌位被改變才繼續執行下面的代碼 System.out.println("sleepThread isInterrupted: " + sleepThread.isInterrupted()); System.out.println("busyThread isInterrupted: " + busyThread.isInterrupted()); } }
輸出:
出處:
https://blog.csdn.net/qq_39682377/article/details/81449451
https://www.zhihu.com/question/41048032