Java中線(xiàn)程中斷的幾種方法小結(jié)
使用線(xiàn)程的stop()來(lái)中斷線(xiàn)程
這種方式是直接調(diào)用線(xiàn)程的stop()方法,可以直接讓線(xiàn)程終止運(yùn)行,是一種很暴力的方式。
public static void test02(){ Thread thread1 = new Thread(()->{ System.out.println("thread1啟動(dòng)了"); while (true){ System.out.println("thread1循環(huán)中..."); } }); thread1.start(); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("準(zhǔn)備關(guān)閉thread1線(xiàn)程"); thread1.stop(); System.out.println("主線(xiàn)程停止"); }
運(yùn)行結(jié)果如下
使用線(xiàn)程的interrupt()來(lái)中斷線(xiàn)程
public static void testInterrupt(){ Thread thread1 = new Thread(() -> { while (true){ boolean interrupted = Thread.currentThread().isInterrupted(); if(interrupted){ System.out.println("thread1線(xiàn)程被中斷"); break; } System.out.println("thread1循環(huán)中..."); } }); thread1.start(); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } thread1.interrupt(); }
運(yùn)行結(jié)果如下
interrupt相比于stop中斷線(xiàn)程的方式更加溫柔,當(dāng)主線(xiàn)程調(diào)用thread1線(xiàn)程的interrupt方法其實(shí)本質(zhì)就是將thread1線(xiàn)程的中斷標(biāo)志設(shè)置為true,僅此而已。被設(shè)置中斷標(biāo)志的線(xiàn)程還是可以繼續(xù)運(yùn)行的,不受影響,也就是如果thread不主動(dòng)結(jié)束線(xiàn)程該線(xiàn)程是不會(huì)停止的。
代碼演示如下
public static void testInterrupt2(){ Thread thread1 = new Thread(() -> { while (true){ boolean interrupted = Thread.currentThread().isInterrupted(); System.out.println("當(dāng)前中斷標(biāo)志位狀態(tài)為:"+interrupted); System.out.println("thread1循環(huán)中..."); } }); thread1.start(); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } thread1.interrupt(); }
運(yùn)行結(jié)果如下
當(dāng)調(diào)用了thread1.interrupt();之后thread1還會(huì)一直無(wú)限執(zhí)行下去。
如果thread1線(xiàn)程處于被阻塞狀態(tài)(例如處于sleep,wait,join等狀態(tài)),在別的線(xiàn)程調(diào)用thread1的interrupt方法,那么線(xiàn)程的中斷狀態(tài)會(huì)被清除,并拋出InterruptedException異常
代碼如下
public static void testInterrupt3(){ Thread thread1 = new Thread(() -> { System.out.println("thread1線(xiàn)程啟動(dòng)了。。。"); try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } }); thread1.start(); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } thread1.interrupt(); }
運(yùn)行結(jié)果如下
1.線(xiàn)程啟動(dòng)是,默認(rèn)中斷標(biāo)志位為false
2.如果main線(xiàn)程調(diào)用了thread1的interrupt()方法,中斷標(biāo)志位就變成了true
3.正常情況,中斷標(biāo)志位為true,如果thread1判斷中斷標(biāo)志位為true就中斷執(zhí)行,則thread1停止,如果thread1線(xiàn)程自己不終止運(yùn)行則不會(huì)停止。
4.異常情況,如果thread1線(xiàn)程正處于阻塞狀態(tài)(例如處于sleep,wait,join等狀態(tài)),將會(huì)把中斷狀態(tài)清除,并且將拋出InterruptedException異常,此時(shí)中斷標(biāo)志位還是false,thread1線(xiàn)程還會(huì)繼續(xù)執(zhí)行。
測(cè)試異常情況,并且循環(huán)不停止的情況,代碼如下
public static void testInterrupt4(){ Thread thread1 = new Thread(() -> { System.out.println("thread1線(xiàn)程啟動(dòng)了。。。"); try { Thread.sleep(5000); } catch (Exception e) { e.printStackTrace(); } while (true){ boolean interrupted = Thread.currentThread().isInterrupted(); if(interrupted){ System.out.println("thread1程序終止"); break; } } }); thread1.start(); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } thread1.interrupt(); }
程序并沒(méi)有停止
5.解決異常情況的方法,就是在catch塊中,需要再次將中斷標(biāo)志位設(shè)置為true,2次調(diào)用才能使中斷標(biāo)志位改為true
public static void testInterrupt5(){ Thread thread1 = new Thread(() -> { System.out.println("thread1線(xiàn)程啟動(dòng)了。。。"); try { Thread.sleep(5000); } catch (Exception e) { // 拋出異常過(guò)后在此調(diào)用interrupt方法 Thread.currentThread().interrupt(); e.printStackTrace(); } while (true){ boolean interrupted = Thread.currentThread().isInterrupted(); if(interrupted){ System.out.println("thread1程序終止"); break; } } }); thread1.start(); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } thread1.interrupt(); }
關(guān)于Thread.interrupted()方法
判斷線(xiàn)程是否被中斷并清除當(dāng)前中斷狀態(tài)
這個(gè)方法做了兩件事情
1.返回當(dāng)前線(xiàn)程的中斷狀態(tài)
2.將當(dāng)前線(xiàn)程的中斷狀態(tài)清零并重新設(shè)置為false,清除線(xiàn)程的中斷狀態(tài)
public static void testInterrupt6(){ System.out.println(Thread.currentThread().getName() + "\t" + Thread.interrupted()); System.out.println(Thread.currentThread().getName() + "\t" + Thread.interrupted()); System.out.println("1111111111111111"); // 中斷標(biāo)志位設(shè)置為true Thread.currentThread().interrupt(); System.out.println("2222222222222222"); System.out.println(Thread.currentThread().getName() + "\t" + Thread.interrupted()); System.out.println(Thread.currentThread().getName() + "\t" + Thread.interrupted()); }
關(guān)于isInterrupted()方法
該方法只會(huì)返回當(dāng)前線(xiàn)程的中斷標(biāo)志位的狀態(tài);不會(huì)清除當(dāng)前線(xiàn)程的中斷標(biāo)志位的狀態(tài)
public static void testInterrupt7(){ System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().isInterrupted()); System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().isInterrupted()); System.out.println("1111111111111111"); // 中斷標(biāo)志位設(shè)置為true Thread.currentThread().interrupt(); System.out.println("2222222222222222"); System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().isInterrupted()); System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().isInterrupted()); }
關(guān)于Thread的靜態(tài)方法interrupted和Thread實(shí)例方法isInterrupted底層源碼
1.interrupted
public static boolean interrupted() { return currentThread().isInterrupted(true); }
2.isInterrupted
public boolean isInterrupted() { return isInterrupted(false); }
本質(zhì)上都是調(diào)用了實(shí)例的isInterrupted方法,只是傳入的參數(shù)有所不同,當(dāng)傳入true時(shí),會(huì)情空當(dāng)前線(xiàn)程的中斷標(biāo)志,重置為false,方傳入false時(shí),不會(huì)清空。
private native boolean isInterrupted(boolean ClearInterrupted);
該方法是被native修飾的方法
總結(jié)
- public void interrupt() 其中interrupt()是一個(gè)實(shí)例方法
它通知目標(biāo)線(xiàn)程中斷,也僅僅是設(shè)置目標(biāo)線(xiàn)程的中斷標(biāo)志位為true. - public boolean isInterrupted() 其中isInterrupted()方法也是一個(gè)實(shí)例方法
它判斷當(dāng)前線(xiàn)程是否被中斷(通過(guò)檢查中斷標(biāo)志位)并獲得中斷標(biāo)志 - public static boolean interrupted() . 該方法是Thread類(lèi)的靜態(tài)方法
返回當(dāng)前線(xiàn)程的中斷狀態(tài)真實(shí)值后會(huì)將當(dāng)前線(xiàn)程的中斷狀態(tài)設(shè)置為false,此方法調(diào)用之后會(huì)清除當(dāng)前線(xiàn)程的中斷標(biāo)志位的狀態(tài)。
通過(guò)共享變量來(lái)控制
1.使用volatile 關(guān)鍵字來(lái)實(shí)現(xiàn)線(xiàn)程中斷
static volatile boolean run = true; public static void main(String[] args) { new Thread(()->{ while (run){ System.out.println("線(xiàn)程1執(zhí)行中..."); } }).start(); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } run = false; System.out.println("主線(xiàn)程結(jié)束"); }
2.使用同步代碼塊synchronized來(lái)實(shí)現(xiàn)線(xiàn)程中斷
static boolean run = true; static Object object = new Object(); public static void main(String[] args) { new Thread(()->{ while (run){ System.out.println("線(xiàn)程1執(zhí)行中..."); synchronized (object){ } } }).start(); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } run = false; System.out.println("主線(xiàn)程結(jié)束"); }
3.使用AtomicBoolean 來(lái)實(shí)現(xiàn)線(xiàn)程中斷
public static void main(String[] args) { AtomicBoolean run = new AtomicBoolean(true); new Thread(()->{ while (run.get()){ System.out.println("線(xiàn)程1執(zhí)行中..."); } }).start(); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } run.set(false); System.out.println("主線(xiàn)程結(jié)束"); }
其運(yùn)行結(jié)果如下
到此這篇關(guān)于Java中線(xiàn)程中斷的幾種方法小結(jié)的文章就介紹到這了,更多相關(guān)Java 線(xiàn)程中斷內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Java中斷一個(gè)線(xiàn)程操作示例
- 聊聊Java 中的線(xiàn)程中斷
- 詳解Java 線(xiàn)程中斷
- Java并發(fā)編程之線(xiàn)程中斷
- java高并發(fā)的線(xiàn)程中斷的幾種方式詳解
- Java線(xiàn)程中斷interrupt的常用方法
- java中斷線(xiàn)程的正確姿勢(shì)完整示例
- java中線(xiàn)程中斷的實(shí)現(xiàn)示例
- Java中的線(xiàn)程中斷機(jī)制和LockSupport詳解
- Java線(xiàn)程中斷及線(xiàn)程中斷的幾種使用場(chǎng)景小結(jié)
- java線(xiàn)程的中斷和同步問(wèn)題的實(shí)現(xiàn)
相關(guān)文章
詳解SpringBoot開(kāi)發(fā)案例之整合Dubbo分布式服務(wù)
這篇文章主要介紹了詳解SpringBoot開(kāi)發(fā)案例之整合Dubbo分布式服務(wù),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-10-10選擇java的理由:java之父訪(fǎng)談實(shí)錄
選擇java的理由:java之父訪(fǎng)談實(shí)錄...2006-12-12Java線(xiàn)程間協(xié)作wait、notify和notifyAll詳解
這篇文章主要介紹了Java線(xiàn)程間協(xié)作wait、notify和notifyAll詳解,在 Java 中可以用 wait、notify 和 notifyAll 來(lái)實(shí)現(xiàn)線(xiàn)程間的通信,盡管關(guān)于wait和notify的概念很基礎(chǔ),它們也都是Object類(lèi)的函數(shù),但用它們來(lái)寫(xiě)代碼卻并不簡(jiǎn)單,,需要的朋友可以參考下2023-10-10SpringBoot基于Redis實(shí)現(xiàn)生成全局唯一ID的方法
在項(xiàng)目中生成全局唯一ID有很多好處,生成全局唯一ID有助于提高系統(tǒng)的可用性、數(shù)據(jù)的完整性和安全性,同時(shí)也方便數(shù)據(jù)的管理和分析,所以本文給大家介紹了SpringBoot基于Redis實(shí)現(xiàn)生成全局唯一ID的方法,文中有詳細(xì)的代碼講解,需要的朋友可以參考下2023-12-12Spring?Boot?Security認(rèn)證之Redis緩存用戶(hù)信息詳解
本文介紹了如何使用Spring Boot Security進(jìn)行認(rèn)證,并通過(guò)Redis緩存用戶(hù)信息以提高系統(tǒng)性能,通過(guò)配置RedisUserDetailsManager,我們成功地將用戶(hù)信息存儲(chǔ)到了Redis中,并在Spring Security中進(jìn)行了集成,需要的朋友可以參考下2024-01-01使用javax.sound實(shí)現(xiàn)簡(jiǎn)單音頻播放
這篇文章主要為大家詳細(xì)介紹了使用javax.sound實(shí)現(xiàn)簡(jiǎn)單音頻播放,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-03-03SpringBoot Redisson 集成的實(shí)現(xiàn)示例
本文主要介紹了SpringBoot Redisson 集成的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-05-05SpringBoot同時(shí)集成Mybatis和Mybatis-plus框架
在實(shí)際開(kāi)發(fā)中,項(xiàng)目里面一般都是Mybatis和Mybatis-Plus公用,但是公用有版本不兼容的問(wèn)題,本文主要介紹了Spring Boot項(xiàng)目中同時(shí)集成Mybatis和Mybatis-plus,具有一檔的參考價(jià)值,感興趣的可以了解一下2024-12-12