淺談Java線程Thread之interrupt中斷解析
這一篇我們說說Java線程Thread的interrupt中斷機制。
中斷線程
線程的thread.interrupt()方法是中斷線程,將會設(shè)置該線程的中斷狀態(tài)位,即設(shè)置為true,中斷的結(jié)果線程是死亡、還是等待新的任務(wù)或是繼續(xù)運行至下一步,就取決于這個程序本身。線程會不時地檢測這個中斷標示位,以判斷線程是否應(yīng)該被中斷(中斷標示值是否為true)。它并不像stop方法那樣會中斷一個正在運行的線程。
判斷線程是否被中斷
判斷某個線程是否已被發(fā)送過中斷請求,請使用Thread.currentThread().isInterrupted()方法(因為它將線程中斷標示位設(shè)置為true后,不會立刻清除中斷標示位,即不會將中斷標設(shè)置為false),而不要使用thread.interrupted()(該方法調(diào)用后會將中斷標示位清除,即重新設(shè)置為false)方法來判斷,下面是線程在循環(huán)中時的中斷方式:
while(!Thread.currentThread().isInterrupted() && more work to do){ do more work }
interrupt之中斷狀態(tài)標記
interrupt中斷機制中有如下方法:
- Thread.interrupt(),設(shè)置當前中斷標記為true(類似屬性的set方法)
- Thread.isInterrupted(),檢測當前的中斷標記(類似屬性的get方法)
- Thread.interrupted(),檢測當前的中斷標記,然后重置中斷標記為false(類似屬性的get方法+set方法)
因此interrupt中斷機制并不是真正的將當前線程中斷,而是一個中斷標記的變化。我們先用例子來測試一下。
public class InterruptTest { //這里用來打印消耗的時間 private static long time = 0; private static void resetTime(){ time = System.currentTimeMillis(); } private static void printContent(String content){ System.out.println(content + " 時間:" + (System.currentTimeMillis() - time)); } public static void main(String[] args) { test1(); } private static void test1(){ Thread1 thread1 = new Thread1(); thread1.start(); //延時3秒后interrupt中斷 try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } thread1.interrupt(); printContent("執(zhí)行中斷"); } private static class Thread1 extends Thread{ @Override public void run() { resetTime(); int num = 0; while (true){ if(isInterrupted()){ printContent("當前線程 isInterrupted"); break; } num++; if(num % 100 == 0){ printContent("num : " + num); } } } } }
以上代碼是開啟一個Thread1線程,在Thread1線程的while循環(huán)中不斷對num加1,每到100的倍數(shù)打印一次(防止打印太快)。然后主線程在sleep了3000毫秒后,調(diào)用Thread1線程的interrupt方法。那么我們看看輸出結(jié)果:
intterupt中斷
可以看到,在耗時3000毫秒左右,也就是主線程sleep之后執(zhí)行thread1.interrupt();后,Thread1線程停止了,而Thread1線程的停止是因為while循環(huán)中的isInterrupted方法返回了true,所以break退出了while循環(huán),也就是說interrupt和isInterrupted在這里起到的作用就相當于setXX和getXX的作用,維護著一個boolean變量。
interrupt之中斷異常處理
當然interrupt機制并不僅僅是一個中斷狀態(tài)位的變化和檢測,它還可以進行中斷異常的處理。我們知道Thread.sleep()方法需要捕獲中斷異常,那接下來我們往其中添加一個sleep延時試試
while (true){ if(isInterrupted()){ printContent("當前線程 isInterrupted"); break; } num++; //sleep一下 try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } if(num % 100 == 0){ printContent("num : " + num); } }
我們再看看輸出結(jié)果:
intterupt中斷
這里我們會發(fā)現(xiàn),sleep睡眠之后,輸出的num值明顯小了好多(沒睡眠時num都達到10億的大小了,看來CPU執(zhí)行簡單運算還是非??斓模?,哈哈,不過這不是重點,重點是是看到輸出了一個異常,還有就是輸出異常后,isInterrupted輸出返回false,Thread1線程又繼續(xù)執(zhí)行下去了,并沒有退出while循環(huán)。那么這是為什么呢?我們只是加了一個sleep睡眠而已。
如果Thread1線程中有執(zhí)行需要捕獲InterruptedException異常的操作,比如Thread的sleep,join方法,Object的wait,Condition的await等,它是強制需要捕獲InterruptedException異常的,那么當thread1.interrupt方法調(diào)用之后,它會給thread1線程拋出一個InterruptedException異常,那么在while循環(huán)中,就能捕獲到這個異常然后這個異常拋出之后,又會馬上將線程中斷標識重置為false,因此在下次的while循環(huán)中判斷isInterrupted時,它是false,也就不會break,然后while循環(huán)會一直執(zhí)行下去。
因此interrupt()方法會根據(jù)thread線程中的run方法里是否有必須捕獲InterruptedException異常的代碼,而做出不同操作:
- 如果沒有必須捕獲InterruptedException異常的代碼(比如Thread.sleep()),則isInterrupted()會返回true,此時可以在isInterrupted的判斷中處理中斷變化。
- 如果有必須捕獲InterruptedException異常的代碼(比如Thread.sleep()),則會拋出InterruptedException異常,并進行捕獲,同時重置isInterrupted為false,此時得在異常捕獲中處理中斷變化。
interrupt的應(yīng)用場景
通常interrupt適用于在線程執(zhí)行中的循環(huán)標記判斷,例如
while(!isInterrupted()){ ... }
但是如果在本次循環(huán)中出現(xiàn)阻塞了,那么線程就無法判斷下次的isInterrupted標記,那么即便調(diào)用了interrupt()方法也無法退出循環(huán),也就無法退出線程。例如
while(!isInterrupted()){ ... while(true){ //線程卡在這里了,則無法響應(yīng)interrupte機制了 } }
這樣的話,interrupt就沒轍了,線程會一直執(zhí)行下去,不會被中斷停止。
測試例子查看 我的GitHub--JavaTest
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Mybatis中關(guān)于自定義mapper.xml時,參數(shù)傳遞的方式及寫法
這篇文章主要介紹了Mybatis中關(guān)于自定義mapper.xml時,參數(shù)傳遞的方式及寫法,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-12-12詳解SpringMVC中的四種跳轉(zhuǎn)方式、視圖解析器問題
這篇文章主要介紹了SpringMVC的四種跳轉(zhuǎn)方式、視圖解析器,springmvc核心配置文件和視圖解析器的使用,添加視圖解析器,通過案例講解四種跳轉(zhuǎn)方式,需要的朋友可以參考下2022-10-10JAVA設(shè)置手動提交事務(wù),回滾事務(wù),提交事務(wù)的操作
這篇文章主要介紹了JAVA設(shè)置手動提交事務(wù),回滾事務(wù),提交事務(wù)的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-04-04