java高并發(fā)的線(xiàn)程中斷的幾種方式詳解
通過(guò)一個(gè)變量控制線(xiàn)程中斷
代碼:
package com.itsoku.chat05; import java.util.concurrent.TimeUnit; /** * 微信公眾號(hào):路人甲Java,專(zhuān)注于java技術(shù)分享(帶你玩轉(zhuǎn) 爬蟲(chóng)、分布式事務(wù)、異步消息服務(wù)、任務(wù)調(diào)度、分庫(kù)分表、大數(shù)據(jù)等),喜歡請(qǐng)關(guān)注! */ public class Demo1 { public volatile static boolean exit = false; public static class T extends Thread { @Override public void run() { while (true) { //循環(huán)處理業(yè)務(wù) if (exit) { break; } } } } public static void setExit() { exit = true; } public static void main(String[] args) throws InterruptedException { T t = new T(); t.start(); TimeUnit.SECONDS.sleep(3); setExit(); } }
代碼中啟動(dòng)了一個(gè)線(xiàn)程,線(xiàn)程的run方法中有個(gè)死循環(huán),內(nèi)部通過(guò)exit變量的值來(lái)控制是否退出。 TimeUnit.SECONDS.sleep(3);讓主線(xiàn)程休眠3秒,此處為什么使用TimeUnit?TimeUnit使用更方便一些,能夠很清晰的控制休眠時(shí)間,底層還是轉(zhuǎn)換為T(mén)hread.sleep實(shí)現(xiàn)的。程序有個(gè)重點(diǎn):volatile關(guān)鍵字,exit變量必須通過(guò)這個(gè)修飾,如果把這個(gè)去掉,程序無(wú)法正常退出。volatile控制了變量在多線(xiàn)程中的可見(jiàn)性,關(guān)于volatile前面的文章中有介紹,此處就不再說(shuō)了。
通過(guò)線(xiàn)程自帶的中斷標(biāo)志控制
示例代碼:
package com.itsoku.chat05; import java.util.concurrent.TimeUnit; /** * 微信公眾號(hào):路人甲Java,專(zhuān)注于java技術(shù)分享(帶你玩轉(zhuǎn) 爬蟲(chóng)、分布式事務(wù)、異步消息服務(wù)、任務(wù)調(diào)度、分庫(kù)分表、大數(shù)據(jù)等),喜歡請(qǐng)關(guān)注! */ public class Demo2 { public static class T extends Thread { @Override public void run() { while (true) { //循環(huán)處理業(yè)務(wù) if (this.isInterrupted()) { break; } } } } public static void main(String[] args) throws InterruptedException { T t = new T(); t.start(); TimeUnit.SECONDS.sleep(3); t.interrupt(); } }
運(yùn)行上面的程序,程序可以正常結(jié)束。線(xiàn)程內(nèi)部有個(gè)中斷標(biāo)志,當(dāng)調(diào)用線(xiàn)程的interrupt()實(shí)例方法之后,線(xiàn)程的中斷標(biāo)志會(huì)被置為true,可以通過(guò)線(xiàn)程的實(shí)例方法isInterrupted()獲取線(xiàn)程的中斷標(biāo)志。
線(xiàn)程阻塞狀態(tài)中如何中斷?
示例代碼:
package com.itsoku.chat05; import java.util.concurrent.TimeUnit; /** * 微信公眾號(hào):路人甲Java,專(zhuān)注于java技術(shù)分享(帶你玩轉(zhuǎn) 爬蟲(chóng)、分布式事務(wù)、異步消息服務(wù)、任務(wù)調(diào)度、分庫(kù)分表、大數(shù)據(jù)等),喜歡請(qǐng)關(guān)注! */ public class Demo3 { public static class T extends Thread { @Override public void run() { while (true) { //循環(huán)處理業(yè)務(wù) //下面模擬阻塞代碼 try { TimeUnit.SECONDS.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } public static void main(String[] args) throws InterruptedException { T t = new T(); t.start(); } }
運(yùn)行上面代碼,發(fā)現(xiàn)程序無(wú)法結(jié)束。
在此先補(bǔ)充幾點(diǎn)知識(shí):
1.調(diào)用線(xiàn)程的interrupt()實(shí)例方法,線(xiàn)程的中斷標(biāo)志會(huì)被置為true
2.當(dāng)線(xiàn)程處于阻塞狀態(tài)時(shí),調(diào)用線(xiàn)程的interrupt()實(shí)例方法,線(xiàn)程內(nèi)部會(huì)觸發(fā)InterruptedException異常,并且會(huì)清除線(xiàn)程內(nèi)部的中斷標(biāo)志(即將中斷標(biāo)志置為false)
那么上面代碼可以調(diào)用線(xiàn)程的interrupt()方法來(lái)引發(fā)InterruptedException異常,來(lái)中斷sleep方法導(dǎo)致的阻塞,調(diào)整一下代碼,如下:
package com.itsoku.chat05; import java.util.concurrent.TimeUnit; /** * 微信公眾號(hào):路人甲Java,專(zhuān)注于java技術(shù)分享(帶你玩轉(zhuǎn) 爬蟲(chóng)、分布式事務(wù)、異步消息服務(wù)、任務(wù)調(diào)度、分庫(kù)分表、大數(shù)據(jù)等),喜歡請(qǐng)關(guān)注! */ public class Demo3 { public static class T extends Thread { @Override public void run() { while (true) { //循環(huán)處理業(yè)務(wù) //下面模擬阻塞代碼 try { TimeUnit.SECONDS.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); this.interrupt(); } if (this.isInterrupted()) { break; } } } } public static void main(String[] args) throws InterruptedException { T t = new T(); t.start(); TimeUnit.SECONDS.sleep(3); t.interrupt(); } }
運(yùn)行結(jié)果:
java.lang.InterruptedException: sleep interrupted at java.lang.Thread.sleep(Native Method) at java.lang.Thread.sleep(Thread.java:340) at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386) at com.itsoku.chat05.Demo3$T.run(Demo3.java:17)
程序可以正常結(jié)束了,分析一下上面代碼,注意幾點(diǎn):
1.main方法中調(diào)用了t.interrupt()方法,此時(shí)線(xiàn)程t內(nèi)部的中斷標(biāo)志會(huì)置為true
2.然后會(huì)觸發(fā)run()方法內(nèi)部的InterruptedException異常,所以運(yùn)行結(jié)果中有異常輸出,上面說(shuō)了,當(dāng)觸發(fā)InterruptedException
異常時(shí)候,線(xiàn)程內(nèi)部的中斷標(biāo)志又會(huì)被清除(變?yōu)閒alse),所以在catch中又調(diào)用了this.interrupt();一次,將中斷標(biāo)志置為false
3.run()方法中通過(guò)this.isInterrupted()來(lái)獲取線(xiàn)程的中斷標(biāo)志,退出循環(huán)(break)
總結(jié)
當(dāng)一個(gè)線(xiàn)程處于被阻塞狀態(tài)或者試圖執(zhí)行一個(gè)阻塞操作時(shí),可以使用 Thread.interrupt()方式中斷該線(xiàn)程,注意此時(shí)將會(huì)拋出一個(gè)InterruptedException的異常,同時(shí)中斷狀態(tài)將會(huì)被復(fù)位(由中斷狀態(tài)改為非中斷狀態(tài))
內(nèi)部有循環(huán)體,可以通過(guò)一個(gè)變量來(lái)作為一個(gè)信號(hào)控制線(xiàn)程是否中斷,注意變量需要volatile修飾
文中的幾種方式可以結(jié)合起來(lái)靈活使用控制線(xiàn)程的中斷
本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
詳解SpringBoot配置文件啟動(dòng)時(shí)動(dòng)態(tài)配置參數(shù)方法
這篇文章主要介紹了詳解SpringBoot配置文件啟動(dòng)時(shí)動(dòng)態(tài)配置參數(shù)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11idea?Maven?插件?docker-maven-plugin?打包docker鏡像上傳到遠(yuǎn)程倉(cāng)庫(kù)的過(guò)程詳解
這篇文章主要介紹了idea Maven插件docker-maven-plugin打包docker鏡像上傳到遠(yuǎn)程倉(cāng)庫(kù),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-05-05Java正則表達(dá)式_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
什么是正則表達(dá)式,正則表達(dá)式的作用是什么?這篇文章主要為大家詳細(xì)介紹了Java正則表達(dá)式的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05SpringBoot中的FailureAnalyzer使用詳解
這篇文章主要介紹了SpringBoot中的FailureAnalyzer使用詳解,Spring Boot的FailureAnalyzer是一個(gè)接口,它用于在Spring Boot應(yīng)用啟動(dòng)失敗時(shí)提供有關(guān)錯(cuò)誤的詳細(xì)信息,這對(duì)于開(kāi)發(fā)者來(lái)說(shuō)非常有用,因?yàn)樗梢詭椭覀兛焖僮R(shí)別問(wèn)題并找到解決方案,需要的朋友可以參考下2023-12-12使用Springboot打成jar包thymeleaf的問(wèn)題
這篇文章主要介紹了使用Springboot打成jar包thymeleaf的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11利用Spring Cloud Zuul實(shí)現(xiàn)動(dòng)態(tài)路由示例代碼
Spring Cloud Zuul路由是微服務(wù)架構(gòu)的不可或缺的一部分,提供動(dòng)態(tài)路由,監(jiān)控,彈性,安全等的邊緣服務(wù)。下面這篇文章主要給大家介紹了關(guān)于利用Spring Cloud Zuul實(shí)現(xiàn)動(dòng)態(tài)路由的相關(guān)資料,需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-09-09java基于C/S模式實(shí)現(xiàn)聊天程序(服務(wù)器)
這篇文章主要為大家詳細(xì)介紹了java基于C/S模式實(shí)現(xiàn)聊天程序的服務(wù)器篇,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-01-01Java設(shè)計(jì)模式之狀態(tài)模式State Pattern詳解
這篇文章主要介紹了Java設(shè)計(jì)模式之狀態(tài)模式State Pattern,狀態(tài)模式允許一個(gè)對(duì)象在其內(nèi)部狀態(tài)改變的時(shí)候改變其行為。這個(gè)對(duì)象看上去就像是改變了它的類(lèi)一樣2022-11-11Java如何計(jì)算兩個(gè)時(shí)間段內(nèi)的工作日天數(shù)
這篇文章主要介紹了Java如何計(jì)算兩個(gè)時(shí)間段內(nèi)的工作日天數(shù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07