Java線程中斷interrupt的常用方法
前言
這里主要探討中斷常用的三個方法:
- interrupt()。在一個線程中調(diào)用需要中斷現(xiàn)成的interrupt()方法,會對該線程發(fā)出信號,將中斷狀態(tài)標(biāo)志為true
- isInterrupted()。判斷當(dāng)前線程的中斷狀態(tài)。
- interrupted()。將線程的中斷狀態(tài)恢復(fù)。
主要使用的阻塞三個方法:
- Object#wait。放棄鎖+等待+重新獲取鎖
- Thread#join?!緟f(xié)作】等待某個線程執(zhí)行完畢
- Thread#sleep。靜態(tài)方法,線程休眠并讓出CPU時間片
==注意:interrupt()不能中斷在運行中的線程,它只能改變中斷狀態(tài)而已。實際完成的是讓受阻塞的線程退出阻塞狀態(tài)。==
確切的說:是被三種方法之一阻塞時,調(diào)用該線程的interrupt()方法,那么線程將拋出一個個InterruptedException中斷異常,從而提早地終結(jié)被阻塞狀態(tài)。
示例說明
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(); ? ? } }
輸出結(jié)果大致如下:
我沒有進入中斷
我沒有進入中斷
我進入中斷了,但我還在跑
我進入中斷了,但我還在跑
我進入中斷了,但我還在跑
...
這里看到,執(zhí)行interrupt()后,對線程執(zhí)行中斷后依然在執(zhí)行,線程依然在運行。
我們調(diào)整一下run方法
public void run() { while (true) { if (Thread.currentThread().isInterrupted()) { System.out.println("我進入中斷了,但我還在跑"); Thread.interrupted();//重置狀態(tài) } else { System.out.println("我沒有進入中斷"); } } }
輸出結(jié)果如下:
我沒有進入中斷
我沒有進入中斷
我進入中斷了,但我還在跑
我沒有進入中斷
我沒有進入中斷
...
這里看到中斷的狀態(tài)重置了,那么我們?nèi)绾稳?yīng)用這個中斷狀態(tài)呢?
注意事項
- 當(dāng)線程A執(zhí)行到wait(),sleep(),join()時,拋出InterruptedException后,中斷狀態(tài)已經(jīng)被系統(tǒng)復(fù)位了,線程A調(diào)用Thread.interrupted()返回的是false。
- 如果線程被調(diào)用了interrupt(),此時該線程并不在阻塞狀態(tài)時,下次執(zhí)行wait(),sleep(),join()時,一樣會拋出InterruptedException,當(dāng)然拋出后該線程的中斷狀態(tài)也會被系統(tǒng)復(fù)位。
案例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(); ? ? } }
執(zhí)行上面的代碼,我們可以看到在拋出異常后,Thread.currentThread().isInterrupted()輸出為false,證明線程的中斷狀態(tài)已經(jīng)復(fù)位了。
另外因為我們是先執(zhí)行了interrupt()然后再進入睡眠狀態(tài),但是依然拋出了異常。
Object#wait 和 Thread.sleep 差異在哪里
因為Object#wait方法會阻塞線程,所以當(dāng)我們執(zhí)行interrupt時,會拋出InterruptedException異常。
那么Object#wait方法阻塞線程會導(dǎo)致的差異在哪里?
==最主要的差別在于sleep方法沒有釋放鎖,而wait方法釋放了鎖,使得其它線程可以使用同步控制塊或者方法。==
總結(jié)
- 調(diào)用interrupt方法,會改變中斷狀態(tài),但不會影響線程的運行狀態(tài)。
- 當(dāng)執(zhí)行了interrupt方法改變中斷狀態(tài)后,線程若執(zhí)行Object#wait,Thread#sleep和Thread#join都會拋出InterruptedException異常,然后復(fù)位中斷狀態(tài)
- 當(dāng)執(zhí)行了interrupt方法改變中斷狀態(tài)后,線程未阻塞,且將要執(zhí)行Object#wait,Thread#sleep和Thread#join阻塞線程時,都會拋出InterruptedException異常,復(fù)位中斷狀態(tài)。
到此這篇關(guān)于Java線程中斷interrupt的常用方法的文章就介紹到這了,更多相關(guān)Java線程中斷interrupt內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
logback FixedWindowRollingPolicy固定窗口算法重命名文件滾動策略
這篇文章主要介紹了FixedWindowRollingPolicy根據(jù)logback 固定窗口算法重命名文件滾動策略源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-11-11SpringBoot 使用 @Value 注解讀取配置文件給靜態(tài)變量賦值
這篇文章主要介紹了SpringBoot 使用 @Value 注解讀取配置文件給靜態(tài)變量賦值,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11Java JVM運行時數(shù)據(jù)區(qū)(Run-Time Data Areas)
運行時數(shù)據(jù)區(qū),是java虛擬機定義的在程序執(zhí)行期間使用的各種運行時的數(shù)據(jù)區(qū),通過JVM運行時數(shù)據(jù)區(qū)圖例給大家展示的很詳細(xì),對JVM 運行時數(shù)據(jù)區(qū)相關(guān)知識感興趣的朋友跟隨小編一起看看吧2021-06-06springboot2如何集成ElasticSearch6.4.3
這篇文章主要介紹了springboot2如何集成ElasticSearch6.4.3問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07