java中線程中斷的實現(xiàn)示例
1、線程中斷 即 線程的取消/關(guān)閉的機制
Java中停止一個線程的主要機制是中斷,中斷并不是強迫終止一個線程,它是一種 協(xié)作機制
,是給線程傳遞一個取消/關(guān)閉信號,由線程自身來決定如何以及何時退出。
停止線程,但這個方法被標記為了過時。 @Deprecated public final void stop() ========================= 返回對應線程的中斷標志位是否為true。 public boolean isInterrupted() 返回當前線程的中斷標志位是否為true,并清空中斷標志位。 public static boolean interrupted() 表示中斷對應的線程。 public void interrupt()
2、線程對中斷interrupt()的反應
2.1、RUNNABLE:線程在運行或具備運行條件只是在等待操作系統(tǒng)調(diào)度
舉個栗子:
public static void main(String[] args) throws InterruptedException { Thread t = new Thread(() -> { while (!Thread.currentThread().isInterrupted()) { System.out.println("線程t 執(zhí)行中..."); } }); t.start(); Thread.sleep(1); t.interrupt(); System.out.println("main exit"); }
RUNNABLE狀態(tài)的線程t
被interrupt()
后,是否終止中斷線程由線程t
自身代碼邏輯決定。
2.2、WAITING/TIMED_WAITING:線程在等待某個條件或超時
線程執(zhí)行如下方法會進入WAITING狀態(tài): public final void join() throws InterruptedException public final void wait() throws InterruptedException 線程執(zhí)行如下方法會進入TIMED_WAITING狀態(tài): public final native void wait(long timeout) throws InterruptedException public static native void sleep(long millis) throws InterruptedException public final synchronized void join(long millis) throws InterruptedException
舉個栗子:
public class ThreadInterrupt { public static void main(String[] args) { Thread t = new Thread(() -> { try { Thread.sleep(10000); } catch (InterruptedException e) { System.out.println("Thread.interrupted() = " + Thread.interrupted()); //Thread.interrupted() = false System.out.println("Thread.interrupted() = " + Thread.interrupted()); //Thread.interrupted() = false } }); t.start(); t.interrupt(); } }
捕獲到InterruptedException,通常表示希望結(jié)束該線程,線程大概有兩種處理方式:
向上傳遞該異常,這使得該方法也變成了一個可中斷的方法,需要調(diào)用者進行處理。
有些情況,不能向上傳遞異常,比如Thread的run方法,它的聲明是固定的,不能拋出任何受檢異常,這時,應該捕獲異常,進行合適的清理操作,清理后,一般應該調(diào)用Thread的interrupt方法設(shè)置中斷標志位,使得其他代碼有辦法知道它發(fā)生了中斷。
2.3、BLOCKED:線程在等待鎖,試圖進入同步塊
舉個栗子:
public class ThreadInterrupt { private final static Object lockObj = new Object(); private static class MyBlockedThread extends Thread { @Override public void run() { System.out.println("MyBlockedThread.run = " + Thread.currentThread().isInterrupted()); synchronized (lockObj) { while (!Thread.currentThread().isInterrupted()) { System.out.println(Thread.currentThread().isInterrupted()); } } System.out.println("exit"); } } public static void main(String[] args) throws InterruptedException { synchronized (lockObj) { MyBlockedThread myBlockedThread = new MyBlockedThread(); myBlockedThread.start(); Thread.sleep(3000); myBlockedThread.interrupt(); myBlockedThread.join(); // join方法會等待線程執(zhí)行完后返回 } } }
myBlockedThread.join();
該行代碼放開注釋掉情況下:線程一直等待鎖 BLOCKED。
com.michael.ThreadInterrupt.MyBlockedThread.run = false
myBlockedThread.join();
該行代碼注釋掉情況下:因為主線程不再等待線程myBlockedThread結(jié)束,釋放鎖lock后,線程myBlockedThread會獲得鎖,然后檢測到發(fā)生了中斷,然后程序退出。
com.michael.ThreadInterrupt.MyBlockedThread.run = false exit
2.4、NEW/TERMINATED:線程還未啟動或已結(jié)束
舉個栗子:
public static void main(String[] args) throws InterruptedException { Thread t = new Thread(() -> { System.out.println("線程t 執(zhí)行..."); }); t.interrupt(); System.out.println("NEW = " + t.isInterrupted()); t.start(); Thread.sleep(100); t.interrupt(); System.out.println("TERMINATE = " + t.isInterrupted()); } ============ 執(zhí)行結(jié)果 ============ NEW = false 線程t 執(zhí)行... TERMINATE = false
2.5、IO操作
如果線程在等待IO操作,尤其是網(wǎng)絡(luò)IO,則會有一些特殊的處理。
- 如果IO通道是可中斷的,即實現(xiàn)了
InterruptibleChannel
接口,則線程的中斷標志位會被設(shè)置,同時線程會收到異常ClosedByInterruptException
。 - 如果線程阻塞于
Selector
調(diào)用,則線程的中斷標志位會被設(shè)置,同時阻塞的調(diào)用會立即返回。 InputStream的read
調(diào)用,該操作是不可中斷的,如果流中沒有數(shù)據(jù),read
會阻塞 (但線程狀態(tài)依然是RUNNABLE
),且不響應interrupt()
,與synchronized
類似,調(diào)用interrupt()
只會設(shè)置線程的中斷標志,而不會真正"中斷"。
3、關(guān)于中斷的經(jīng)驗
Java中取消/關(guān)閉線程技術(shù)是中斷,但它是一種協(xié)作機制,不會強制終止線程。線程在不同狀態(tài)和IO操作時對中斷的反應有所不同。
作為線程的實現(xiàn)者:應該提供明確的取消/關(guān)閉方法,并用文檔描述清楚其行為。
作為線程的調(diào)用者:應該使用其取消/關(guān)閉方法,而不是貿(mào)然調(diào)用interrupt()方法。
到此這篇關(guān)于java中線程中斷的實現(xiàn)示例的文章就介紹到這了,更多相關(guān)java 線程中斷內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot通過JSON傳遞請求參數(shù)的實例詳解
這篇文章主要介紹了SpringBoot通過JSON傳遞請求參數(shù),示例介紹SpringMVC如何通過JSON格式傳遞入?yún)?,代碼簡單易懂,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-11-11SpringBoot自定義maven-plugin插件整合asm代碼插樁
本文主要介紹了SpringBoot自定義maven-plugin插件整合asm代碼插樁,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-02-02mybatis動態(tài)sql之Map參數(shù)的講解
今天小編就為大家分享一篇關(guān)于mybatis動態(tài)sql之Map參數(shù)的講解,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-03-03package打包一個springcloud項目的某個微服務(wù)報錯問題
這篇文章主要介紹了package打包一個springcloud項目的某個微服務(wù)報錯問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-07-07