java中線程中斷的實(shí)現(xiàn)示例
1、線程中斷 即 線程的取消/關(guān)閉的機(jī)制
Java中停止一個(gè)線程的主要機(jī)制是中斷,中斷并不是強(qiáng)迫終止一個(gè)線程,它是一種 協(xié)作機(jī)制
,是給線程傳遞一個(gè)取消/關(guān)閉信號(hào),由線程自身來(lái)決定如何以及何時(shí)退出。
停止線程,但這個(gè)方法被標(biāo)記為了過(guò)時(shí)。 @Deprecated public final void stop() ========================= 返回對(duì)應(yīng)線程的中斷標(biāo)志位是否為true。 public boolean isInterrupted() 返回當(dāng)前線程的中斷標(biāo)志位是否為true,并清空中斷標(biāo)志位。 public static boolean interrupted() 表示中斷對(duì)應(yīng)的線程。 public void interrupt()
2、線程對(duì)中斷interrupt()的反應(yīng)
2.1、RUNNABLE:線程在運(yùn)行或具備運(yùn)行條件只是在等待操作系統(tǒng)調(diào)度
舉個(gè)栗子:
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:線程在等待某個(gè)條件或超時(shí)
線程執(zhí)行如下方法會(huì)進(jìn)入WAITING狀態(tài): public final void join() throws InterruptedException public final void wait() throws InterruptedException 線程執(zhí)行如下方法會(huì)進(jìn)入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
舉個(gè)栗子:
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é)束該線程,線程大概有兩種處理方式:
向上傳遞該異常,這使得該方法也變成了一個(gè)可中斷的方法,需要調(diào)用者進(jìn)行處理。
有些情況,不能向上傳遞異常,比如Thread的run方法,它的聲明是固定的,不能拋出任何受檢異常,這時(shí),應(yīng)該捕獲異常,進(jìn)行合適的清理操作,清理后,一般應(yīng)該調(diào)用Thread的interrupt方法設(shè)置中斷標(biāo)志位,使得其他代碼有辦法知道它發(fā)生了中斷。
2.3、BLOCKED:線程在等待鎖,試圖進(jìn)入同步塊
舉個(gè)栗子:
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方法會(huì)等待線程執(zhí)行完后返回 } } }
myBlockedThread.join();
該行代碼放開(kāi)注釋掉情況下:線程一直等待鎖 BLOCKED。
com.michael.ThreadInterrupt.MyBlockedThread.run = false
myBlockedThread.join();
該行代碼注釋掉情況下:因?yàn)橹骶€程不再等待線程myBlockedThread結(jié)束,釋放鎖lock后,線程myBlockedThread會(huì)獲得鎖,然后檢測(cè)到發(fā)生了中斷,然后程序退出。
com.michael.ThreadInterrupt.MyBlockedThread.run = false exit
2.4、NEW/TERMINATED:線程還未啟動(dòng)或已結(jié)束
舉個(gè)栗子:
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,則會(huì)有一些特殊的處理。
- 如果IO通道是可中斷的,即實(shí)現(xiàn)了
InterruptibleChannel
接口,則線程的中斷標(biāo)志位會(huì)被設(shè)置,同時(shí)線程會(huì)收到異常ClosedByInterruptException
。 - 如果線程阻塞于
Selector
調(diào)用,則線程的中斷標(biāo)志位會(huì)被設(shè)置,同時(shí)阻塞的調(diào)用會(huì)立即返回。 InputStream的read
調(diào)用,該操作是不可中斷的,如果流中沒(méi)有數(shù)據(jù),read
會(huì)阻塞 (但線程狀態(tài)依然是RUNNABLE
),且不響應(yīng)interrupt()
,與synchronized
類(lèi)似,調(diào)用interrupt()
只會(huì)設(shè)置線程的中斷標(biāo)志,而不會(huì)真正"中斷"。
3、關(guān)于中斷的經(jīng)驗(yàn)
Java中取消/關(guān)閉線程技術(shù)是中斷,但它是一種協(xié)作機(jī)制,不會(huì)強(qiáng)制終止線程。線程在不同狀態(tài)和IO操作時(shí)對(duì)中斷的反應(yīng)有所不同。
作為線程的實(shí)現(xiàn)者:應(yīng)該提供明確的取消/關(guān)閉方法,并用文檔描述清楚其行為。
作為線程的調(diào)用者:應(yīng)該使用其取消/關(guān)閉方法,而不是貿(mào)然調(diào)用interrupt()方法。
到此這篇關(guān)于java中線程中斷的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)java 線程中斷內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
如何將Java與C#時(shí)間進(jìn)行互相轉(zhuǎn)換
這篇文章主要介紹了Java與C#時(shí)間互轉(zhuǎn)的方法以及JAVA日期、C#日期計(jì)算說(shuō)明,需要的朋友可以參考下2022-11-11SpringBoot通過(guò)JSON傳遞請(qǐng)求參數(shù)的實(shí)例詳解
這篇文章主要介紹了SpringBoot通過(guò)JSON傳遞請(qǐng)求參數(shù),示例介紹SpringMVC如何通過(guò)JSON格式傳遞入?yún)?,代碼簡(jiǎn)單易懂,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-11-11SpringBoot自定義maven-plugin插件整合asm代碼插樁
本文主要介紹了SpringBoot自定義maven-plugin插件整合asm代碼插樁,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02SpringMVC通過(guò)攔截器實(shí)現(xiàn)IP黑名單
這篇文章主要為大家詳細(xì)介紹了SpringMVC通過(guò)攔截器實(shí)現(xiàn)IP黑名單,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-08-08Java死鎖代碼實(shí)例及產(chǎn)生死鎖必備的四個(gè)條件
這篇文章主要介紹了Java死鎖代碼實(shí)例及產(chǎn)生死鎖必備的四個(gè)條件,Java 發(fā)生死鎖的根本原因是,在申請(qǐng)鎖時(shí)發(fā)生了交叉閉環(huán)申請(qǐng),synchronized在開(kāi)發(fā)中最好不要嵌套使用,容易導(dǎo)致死鎖,需要的朋友可以參考下2024-01-01利用Java實(shí)現(xiàn)網(wǎng)站聚合工具
互聯(lián)網(wǎng)上有數(shù)以萬(wàn)億計(jì)的網(wǎng)站,每個(gè)網(wǎng)站大都具有一定的功能。搜索引擎雖然對(duì)互聯(lián)網(wǎng)上的部分網(wǎng)站建立了索引,但是其作為一個(gè)大而全的搜索系統(tǒng),無(wú)法很好的定位到一些特殊的需求。因此本文將介紹一個(gè)用java實(shí)現(xiàn)的網(wǎng)站數(shù)據(jù)聚合工具,需要的可以參考一下2022-01-01mybatis動(dòng)態(tài)sql之Map參數(shù)的講解
今天小編就為大家分享一篇關(guān)于mybatis動(dòng)態(tài)sql之Map參數(shù)的講解,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-03-03package打包一個(gè)springcloud項(xiàng)目的某個(gè)微服務(wù)報(bào)錯(cuò)問(wèn)題
這篇文章主要介紹了package打包一個(gè)springcloud項(xiàng)目的某個(gè)微服務(wù)報(bào)錯(cuò)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07