Java執行緒中斷
阿新 • • 發佈:2020-12-15
Java執行緒中斷
什麼是執行緒中斷
中斷是給執行緒的一個指示,告訴它應該停止正在做的事並去做其他事情(一般都是結束這個執行緒)。比如360正在執行防毒掃描,我們點選“停止檢測”就是一次執行緒中斷。一個執行緒究竟要怎麼響應中斷請求取決於程式設計師,如果這個執行緒需要處理的任務很重要,那麼執行緒可以忽略這個中斷提醒。但一般相應中斷的方法都是將該執行緒終止。
中斷原理
每個執行緒物件中都有一個boolean型別的狀態位(不是Thread類中的欄位,應該在C++原始碼中),表示是否有中斷請求(該請求可以來自所有執行緒,包括被中斷的執行緒本身)。執行緒在執行某些方法時,總會不時的檢測中斷位,看看有沒有中斷請求,如果有就進行相應的處理。
Java 中斷機制是一種協作機制,也就是說通過中斷並不能直接終止另一個執行緒(僅僅是改變了中斷位),而需要被中斷的執行緒自己處理中斷(可以忽略,也可以終止自己)。
中斷位
獲取中斷位狀態
主要有兩種方法:
- 一種是Thread的靜態方法interrupted,該方法會檢測執行緒是否有中斷請求,如果中斷位為true,即目前該執行緒有中斷請求,那麼該方法會返回true並且將中斷位重新設定位預設值false。
- 另一種是Thread物件的例項方法,isInterrupted。該方法也會檢測執行緒是否有中斷請求,這一點與interrupted方法相同。但不同的是,isInterrupted不會改變中斷位的狀態。
改變中斷位狀態
也是兩種:
- 主要是通過Thread物件的例項方法:interrupt()。呼叫該方法後,執行緒的中斷位會被設定為true,但並不是真正的中斷了該執行緒。
- 也可以通過interrupted()方法將中斷位設定為false。
中斷的程式碼實現
主要可以分為兩大類,一種是執行緒呼叫非阻塞方法時發生中斷,另一種是呼叫阻塞方式時發生中斷。當執行緒在執行方法時發生中斷,那麼就會丟擲InterruptedException異常,並且將狀態位設定位false。
執行非阻塞方法時發生中斷
public class InterruptTest01 { public static void main(String[] args) throws InterruptedException { Thread interruptThread = new Thread(()->{ System.out.println("interruptThread執行緒正在執行。。。。。。"); while (true) { if (Thread.currentThread().isInterrupted()){ System.out.println("檢測到中斷訊號,終止執行緒"); // 或者其他處理 return; } } }, "interruptThread"); interruptThread.start(); TimeUnit.SECONDS.sleep(5); System.out.println(Thread.currentThread().getName() + "執行緒向" + interruptThread.getName() + "執行緒發出中斷訊號。。。。"); interruptThread.interrupt(); } }
執行阻塞方法時發生中斷
package thread;
import java.sql.Time;
import java.util.concurrent.TimeUnit;
/**
* @author: OnlyOne
* @create: 2020-12-15 15:52
* @description:
**/
public class InterruptTest02 {
public static void main(String[] args) throws InterruptedException {
Thread interruptThread = new Thread(()->{
try {
while (true) {
System.out.println("interruptThread執行緒即將沉睡5秒。。。。。");
TimeUnit.SECONDS.sleep(5);
}
}catch (InterruptedException e) {
System.out.println("捕獲到InterruptedException異常。。。。");
System.out.println("此時中斷位:" + Thread.currentThread().isInterrupted());
return;
}
}, "interruptThread");
interruptThread.start();
// main執行緒沉睡兩秒,好讓interruptThread執行緒沉睡
TimeUnit.SECONDS.sleep(2);
System.out.println(Thread.currentThread().getName() + "執行緒向" + interruptThread.getName() + "執行緒發出中斷訊號。。。。");
interruptThread.interrupt();
}
}
以上程式中,當main執行緒向interruptThread執行緒發出中斷請求後,interruptThread的狀態位被設定為true。但此時interruptThread執行緒正在呼叫阻塞方法,因此就會丟擲InterruptedException異常。
參考
https://www.infoq.cn/article/java-interrupt-mechanism/
https://www.jianshu.com/p/a8abe097d4ed