Thread類interrupt interrupted及isInterrupted區(qū)別
前言
在java Thread類中,我們會看到interrupt()、interrupted()及isInterrupted(),在大多數(shù)情況下,我們都不會使用到它們,但是有一個InterruptedException
類我們應該是經常會遇到的,例如:
public static void main(String[] args) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } }
那么你知道InterruptedException
異常是如何觸發(fā)的嘛?
如何觸發(fā)InterruptedException
我們發(fā)現(xiàn),在sleep()、wait()、join()等阻塞方法上才會需要拋InterruptedException
:
public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(() -> { try { // 執(zhí)行睡眠1秒,馬上會被主線程打斷 Thread.sleep(1000); } catch (InterruptedException e) { // 觸發(fā)InterruptedException異常 e.printStackTrace(); // 打印是否被打斷 System.out.println(Thread.currentThread().isInterrupted()); } }); // 主線程啟動線程t1 t1.start(); // 主線程打斷t1 t1.interrupt(); // 等等t1執(zhí)行完畢 t1.join(); }
1.我們創(chuàng)建了一個線程對象t1,t1執(zhí)行邏輯就是sleep 1秒鐘;不過我們會發(fā)現(xiàn)線程t1根本sleep不了那么久,因為主線程馬上就會打斷它;線程t1被打斷后,會打印出異常堆棧,并輸出線程t1的打斷標記;
2.在主線程中,啟動線程t1后,那么就打斷線程t1;
3.等待線程t1邏輯全部執(zhí)行完畢后主線程退出;
我們會發(fā)現(xiàn),輸出的線程t1的打斷標記一致是false;咱們明明已經調用了t1.interrupt()
,并且也觸發(fā)了InterruptedException
異常,這到底是為什么導致上面代碼線程t1的打斷標記一直是false呢?
我們從JDK源碼中找到了這樣一段注釋:
簡單翻譯如下:如果任何線程打斷當前線程,當前線程的打斷標記在InterruptedException拋出時會被清除掉。
所以說,我們在捕捉到InterruptedException
后想要再拿到線程t1的打斷標記基本上是不可能的。
interrupt()的作用
在Thread中,我們調用interrupt()
并不會阻止目標線程繼續(xù)執(zhí)行,它只是給目標線程打上一個標記:
public static void main(String[] args) throws InterruptedException { // 創(chuàng)建線程t1 Thread t1 = new Thread(() -> { int i = 0; // 循環(huán)自增 while (true) { System.out.println(i); i++; // 判斷是否有打斷標記 if(Thread.currentThread().isInterrupted()){ System.out.println("線程被打斷,跳出循環(huán)"); // 如果有打斷標記,就跳出循環(huán) break; } } }); // 啟動線程t1 t1.start(); // 打斷線程t1 t1.interrupt(); // 等待線程t1執(zhí)行完畢 t1.join(); }
1.在上述代碼中,如果刪掉break代碼,那么線程t1會一直死循環(huán),說明interrupt()是無法阻止線程t1執(zhí)行的;
2.在非阻塞代碼中,我們是可以拿到線程t1的打斷標記的,也就是說,非阻塞代碼不會清除線程的打斷標記;
interrupted()及isInterrupted()的區(qū)別
我們可以看一下Thread類中這兩個方法的源代碼:
// 靜態(tài)方法,調用當前線程的isInterrupted(true) public static boolean interrupted() { return currentThread().isInterrupted(true); } // 對象方法,調用當前線程對象的isInterrupted(false) public boolean isInterrupted() { return isInterrupted(false); }
根據(jù)上面源碼,我們發(fā)現(xiàn)了interrupted()
是一個靜態(tài)方法,是可以直接通過Thread.interrupted()
調用的;isInterrupted()
方法是線程對象方法,是需要通過線程對象調用的;我們在前面代碼中使用Thread.currentThread().isInterrupted()
就是通過線程對象調用的;
另一個區(qū)別就是兩個方法傳遞的參數(shù)不同,interrupted()
傳遞的true,isInterrupted()
傳遞的是false;這兩個參數(shù)的作用是是否清除打斷標記,也就是說,如果調用Thread.interrupted()
返回true后,我們的打斷標記會被清除,那么再次調用Thread.interrupted()
拿到的就是false;isInterrupted()
方法就不會清除打斷標記,每次調用isInterrupted()
結果都不變;
小結
通過上述示例演示,我們可以總結出如下幾點:
1.interrupt()作用是給目標線程打上打斷標記,并不會阻止目標線程的繼續(xù)執(zhí)行;
2.出現(xiàn)InterruptedException后,打斷標記會被清除;
3.interrupted()是靜態(tài)方法,并且會清除線程打斷標記;isInterrupted()是線程對象方法,不會清除打斷標記;
以上就是Thread類interrupt interrupted及isInterrupted區(qū)別的詳細內容,更多關于Thread類interrupt interrupted的資料請關注腳本之家其它相關文章!
相關文章
spring?boot如何配置靜態(tài)路徑詳解(404出現(xiàn)的坑)
這篇文章主要給大家介紹了關于spring?boot如何配置靜態(tài)路徑的相關資料,文中通過實例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2022-02-02Spring Boot2.0中SpringWebContext找不到無法使用的解決方法
這篇文章主要給大家介紹了關于Spring Boot2.0中SpringWebContext找不到無法使用的解決方法,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考借鑒,下面隨著小編來一起學習學習吧2018-12-12