Java執行緒里:“中斷”就是指“終止”,與作業系統里的"中斷"、“例外”是完全不同的概念;
由于stop()方法過于暴力,可能導致資源回收無法風險、開銷過大等問題,此方法已過期,故Java中沒有強制中斷執行緒的手段;但可以呼叫interupt()、interupted()方法來向行程提出中斷請求,待行程自行處理,這是一種更優雅的中斷方式,
注意:當需要中斷執行緒時,最佳實踐就是利用執行緒的中斷位,而不是自定義中斷狀態,因為當執行緒被阻塞時,原生中斷位仍然會被監聽,而自定義的則不能,
以下兩類場景會應用到執行緒中斷:
-
用來打斷正在阻塞的執行緒:阻塞在sleep/wait/join等方法上、 阻塞在io-channel讀寫操作上、阻塞在io-channel-selector上,
-
打斷正常執行的執行緒:需要在目標執行緒內部檢測中斷位,并由用戶手動終止,來做出回應,
-
interrupt()
實體方法,在執行緒內外都可發起呼叫;其作用是中斷此執行緒(此執行緒不一定是當前執行緒,而是指呼叫該方法的Thread實體所代表的執行緒),但實際上只是給執行緒設定一個中斷標志,執行緒仍會繼續運行,)作用與正常執行緒會將中斷標記設定為true,但是作用于阻塞執行緒會將中斷標志重繪false(中斷標記默認為false,重繪就是重新刷會默認), -
interrupted()
靜態方法,只能在執行緒內部呼叫;作用是測驗當前執行緒是否被中斷(檢查中斷標志),回傳一個boolean并清除中斷狀態,第二次再呼叫時中斷狀態已經被清除,將回傳一個false,
-
-
isInterrupted()
作用是只檢測此執行緒是否被中斷 ,不清除中斷狀態,
- 不在執行緒內部檢測中斷位并手動回應中斷,執行緒將無限執行下去:
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
while (true) {
System.err.println("子執行緒");
}
});
thread.start();
System.out.println("---" + thread.isInterrupted()); // ---false
/**
* 這主執行緒只是改變了子執行緒的中斷位改為了true
* 由于子線內部并沒有就中斷位進行檢測和處理,故子執行緒并不會終止,會無限列印下去
*/
thread.interrupt();
TimeUnit.SECONDS.sleep(1);
System.err.println("===" + thread.isInterrupted()); // ===true
}
- 在非阻塞執行緒內部手動回應中斷:
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
while (!Thread.currentThread().isInterrupted()) {
System.out.println(Thread.currentThread().isInterrupted());
System.err.println("子執行緒");
}
});
thread.start();
System.out.println("---" + thread.isInterrupted()); // ---false
/**
* 這主執行緒只是改變了子執行緒的中斷位改為了true
*/
TimeUnit.SECONDS.sleep(3);
thread.interrupt();
System.err.println("===" + thread.isInterrupted()); // ===true
}
- 在非阻塞執行緒內部手動回應中斷:
/**
* 當子執行緒需要回應主執行緒的中斷請求,而停止時,可以通過在子執行緒中實時檢測其自身的中斷狀態來達到停止的目的
*
* @param args
*/
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
// 實時檢測自身中斷狀態
while (!Thread.currentThread().isInterrupted()) {
System.err.println("子執行緒");
}
});
thread.start();
TimeUnit.SECONDS.sleep(2);
// 修改子執行緒的中斷狀態
thread.interrupt();
}
- 中斷阻塞中的執行緒:
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
while (!Thread.currentThread().isInterrupted()) {
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
// 例外被捕獲后,阻塞被打破、中斷位被設為false,所以例外中永遠輸出false
System.out.println("2 ----" + Thread.currentThread().isInterrupted()); // 2 ----false
System.err.println("回收資源");
e.printStackTrace();
}
System.err.println("子執行緒邏輯");
}
});
thread.start();
TimeUnit.SECONDS.sleep(1);
thread.interrupt();
System.out.println(thread.isInterrupted()); // true
TimeUnit.SECONDS.sleep(5);
}
- 優雅中斷非阻塞執行緒:
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
while (true) {
if (Thread.interrupted()) {
System.out.println("清理資源");
break;
}
System.err.println("子執行緒邏輯");
}
});
thread.start();
TimeUnit.SECONDS.sleep(1);
thread.interrupt();
}
學習使我充實,分享給我快樂!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/543613.html
標籤:其他
上一篇:fusion app 常用小技巧
