目錄
- 前言
- 示例說明
- 注意事項
-
- 案例1
- Object#wait 和 Thread.sleep 差異在哪裡
- 總結
前言
這裡主要探讨中斷常用的三個方法:
- interrupt()。在一個線程中調用需要中斷現成的interrupt()方法,會對該線程發出信号,将中斷狀态标志為true
- isInterrupted()。判斷目前線程的中斷狀态。
- interrupted()。将線程的中斷狀态恢複。
主要使用的阻塞三個方法:
- Object#wait。放棄鎖+等待+重新擷取鎖
- Thread#join。【協作】等待某個線程執行完畢
- Thread#sleep。靜态方法,線程休眠并讓出CPU時間片
注意:interrupt()不能中斷在運作中的線程,它隻能改變中斷狀态而已。實際完成的是讓受阻塞的線程退出阻塞狀态。
确切的說:是被三種方法之一阻塞時,調用該線程的interrupt()方法,那麼線程将抛出一個個InterruptedException中斷異常,進而提早地終結被阻塞狀态。
示例說明
public class Runner3 implements Runnable {
@Override
public void run() {
while (true) {
if (Thread.currentThread().isInterrupted()) {
System.out.println("我進入中斷了,但我還在跑");
} else {
System.out.println("我沒有進入中斷");
}
}
}
public static void main(String[] args) {
Runner3 runner3 = new Runner3();
Thread thread3 = new Thread(runner3);
thread3.start();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread3.interrupt();
}
}
輸出結果大緻如下:
我沒有進入中斷
我沒有進入中斷
我進入中斷了,但我還在跑
我進入中斷了,但我還在跑
我進入中斷了,但我還在跑
...
這裡看到,執行interrupt()後,對線程執行中斷後依然在執行,線程依然在運作。
我們調整一下run方法
public void run() {
while (true) {
if (Thread.currentThread().isInterrupted()) {
System.out.println("我進入中斷了,但我還在跑");
Thread.interrupted();//重置狀态
} else {
System.out.println("我沒有進入中斷");
}
}
}
輸出結果如下:
我沒有進入中斷
我沒有進入中斷
我進入中斷了,但我還在跑
我沒有進入中斷
我沒有進入中斷
...
這裡看到中斷的狀态重置了,那麼我們如何去應用這個中斷狀态呢?
注意事項
- 當線程A執行到wait(),sleep(),join()時,抛出InterruptedException後,中斷狀态已經被系統複位了,線程A調用Thread.interrupted()傳回的是false。
- 如果線程被調用了interrupt(),此時該線程并不在阻塞狀态時,下次執行wait(),sleep(),join()時,一樣會抛出InterruptedException,當然抛出後該線程的中斷狀态也會被系統複位。
案例1
public class Runner3 implements Runnable {
@Override
public void run() {
while (true) {
if (Thread.currentThread().isInterrupted()) {
System.out.println("我進入中斷了,但我還在跑");
//
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("2"+Thread.currentThread().isInterrupted());
//輸出false
}
} else {
System.out.println("我沒有進入中斷");
}
}
}
public static void main(String[] args) {
Runner3 runner3 = new Runner3();
Thread thread3 = new Thread(runner3);
thread3.start();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread3.interrupt();
}
}
執行上面的代碼,我們可以看到在抛出異常後,Thread.currentThread().isInterrupted()輸出為false,證明線程的中斷狀态已經複位了。
另外因為我們是先執行了interrupt()然後再進入睡眠狀态,但是依然抛出了異常。
Object#wait 和 Thread.sleep 差異在哪裡
因為Object#wait方法會阻塞線程,是以當我們執行interrupt時,會抛出InterruptedException異常。
那麼Object#wait方法阻塞線程會導緻的差異在哪裡?
最主要的差别在于sleep方法沒有釋放鎖,而wait方法釋放了鎖,使得其它線程可以使用同步控制塊或者方法。
總結
- 調用interrupt方法,會改變中斷狀态,但不會影響線程的運作狀态。
- 當執行了interrupt方法改變中斷狀态後,線程若執行Object#wait,Thread#sleep和Thread#join都會抛出InterruptedException異常,然後複位中斷狀态
- 當執行了interrupt方法改變中斷狀态後,線程未阻塞,且将要執行Object#wait,Thread#sleep和Thread#join阻塞線程時,都會抛出InterruptedException異常,複位中斷狀态。