Java中線程中斷的幾種方法小結(jié)
使用線程的stop()來中斷線程
這種方式是直接調(diào)用線程的stop()方法,可以直接讓線程終止運(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線程");
thread1.stop();
System.out.println("主線程停止");
}
運(yùn)行結(jié)果如下

使用線程的interrupt()來中斷線程
public static void testInterrupt(){
Thread thread1 = new Thread(() -> {
while (true){
boolean interrupted = Thread.currentThread().isInterrupted();
if(interrupted){
System.out.println("thread1線程被中斷");
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中斷線程的方式更加溫柔,當(dāng)主線程調(diào)用thread1線程的interrupt方法其實(shí)本質(zhì)就是將thread1線程的中斷標(biāo)志設(shè)置為true,僅此而已。被設(shè)置中斷標(biāo)志的線程還是可以繼續(xù)運(yùn)行的,不受影響,也就是如果thread不主動(dòng)結(jié)束線程該線程是不會(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ì)一直無限執(zhí)行下去。
如果thread1線程處于被阻塞狀態(tài)(例如處于sleep,wait,join等狀態(tài)),在別的線程調(diào)用thread1的interrupt方法,那么線程的中斷狀態(tài)會(huì)被清除,并拋出InterruptedException異常
代碼如下
public static void testInterrupt3(){
Thread thread1 = new Thread(() -> {
System.out.println("thread1線程啟動(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.線程啟動(dòng)是,默認(rèn)中斷標(biāo)志位為false
2.如果main線程調(diào)用了thread1的interrupt()方法,中斷標(biāo)志位就變成了true
3.正常情況,中斷標(biāo)志位為true,如果thread1判斷中斷標(biāo)志位為true就中斷執(zhí)行,則thread1停止,如果thread1線程自己不終止運(yùn)行則不會(huì)停止。
4.異常情況,如果thread1線程正處于阻塞狀態(tài)(例如處于sleep,wait,join等狀態(tài)),將會(huì)把中斷狀態(tài)清除,并且將拋出InterruptedException異常,此時(shí)中斷標(biāo)志位還是false,thread1線程還會(huì)繼續(xù)執(zhí)行。
測(cè)試異常情況,并且循環(huán)不停止的情況,代碼如下
public static void testInterrupt4(){
Thread thread1 = new Thread(() -> {
System.out.println("thread1線程啟動(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();
}

程序并沒有停止
5.解決異常情況的方法,就是在catch塊中,需要再次將中斷標(biāo)志位設(shè)置為true,2次調(diào)用才能使中斷標(biāo)志位改為true
public static void testInterrupt5(){
Thread thread1 = new Thread(() -> {
System.out.println("thread1線程啟動(dòng)了。。。");
try {
Thread.sleep(5000);
} catch (Exception e) {
// 拋出異常過后在此調(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()方法
判斷線程是否被中斷并清除當(dāng)前中斷狀態(tài)
這個(gè)方法做了兩件事情
1.返回當(dāng)前線程的中斷狀態(tài)
2.將當(dāng)前線程的中斷狀態(tài)清零并重新設(shè)置為false,清除線程的中斷狀態(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)前線程的中斷標(biāo)志位的狀態(tài);不會(huì)清除當(dāng)前線程的中斷標(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)前線程的中斷標(biāo)志,重置為false,方傳入false時(shí),不會(huì)清空。
private native boolean isInterrupted(boolean ClearInterrupted);
該方法是被native修飾的方法
總結(jié)
- public void interrupt() 其中interrupt()是一個(gè)實(shí)例方法
它通知目標(biāo)線程中斷,也僅僅是設(shè)置目標(biāo)線程的中斷標(biāo)志位為true. - public boolean isInterrupted() 其中isInterrupted()方法也是一個(gè)實(shí)例方法
它判斷當(dāng)前線程是否被中斷(通過檢查中斷標(biāo)志位)并獲得中斷標(biāo)志 - public static boolean interrupted() . 該方法是Thread類的靜態(tài)方法
返回當(dāng)前線程的中斷狀態(tài)真實(shí)值后會(huì)將當(dāng)前線程的中斷狀態(tài)設(shè)置為false,此方法調(diào)用之后會(huì)清除當(dāng)前線程的中斷標(biāo)志位的狀態(tài)。
通過共享變量來控制
1.使用volatile 關(guān)鍵字來實(shí)現(xiàn)線程中斷
static volatile boolean run = true;
public static void main(String[] args) {
new Thread(()->{
while (run){
System.out.println("線程1執(zhí)行中...");
}
}).start();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
run = false;
System.out.println("主線程結(jié)束");
}
2.使用同步代碼塊synchronized來實(shí)現(xiàn)線程中斷
static boolean run = true;
static Object object = new Object();
public static void main(String[] args) {
new Thread(()->{
while (run){
System.out.println("線程1執(zhí)行中...");
synchronized (object){
}
}
}).start();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
run = false;
System.out.println("主線程結(jié)束");
}
3.使用AtomicBoolean 來實(shí)現(xiàn)線程中斷
public static void main(String[] args) {
AtomicBoolean run = new AtomicBoolean(true);
new Thread(()->{
while (run.get()){
System.out.println("線程1執(zhí)行中...");
}
}).start();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
run.set(false);
System.out.println("主線程結(jié)束");
}
其運(yùn)行結(jié)果如下

到此這篇關(guān)于Java中線程中斷的幾種方法小結(jié)的文章就介紹到這了,更多相關(guān)Java 線程中斷內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解SpringBoot開發(fā)案例之整合Dubbo分布式服務(wù)
這篇文章主要介紹了詳解SpringBoot開發(fā)案例之整合Dubbo分布式服務(wù),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-10-10
Java線程間協(xié)作wait、notify和notifyAll詳解
這篇文章主要介紹了Java線程間協(xié)作wait、notify和notifyAll詳解,在 Java 中可以用 wait、notify 和 notifyAll 來實(shí)現(xiàn)線程間的通信,盡管關(guān)于wait和notify的概念很基礎(chǔ),它們也都是Object類的函數(shù),但用它們來寫代碼卻并不簡(jiǎn)單,,需要的朋友可以參考下2023-10-10
SpringBoot基于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-12
Spring?Boot?Security認(rèn)證之Redis緩存用戶信息詳解
本文介紹了如何使用Spring Boot Security進(jìn)行認(rèn)證,并通過Redis緩存用戶信息以提高系統(tǒng)性能,通過配置RedisUserDetailsManager,我們成功地將用戶信息存儲(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-03
SpringBoot Redisson 集成的實(shí)現(xiàn)示例
本文主要介紹了SpringBoot Redisson 集成的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-05-05
SpringBoot同時(shí)集成Mybatis和Mybatis-plus框架
在實(shí)際開發(fā)中,項(xiàng)目里面一般都是Mybatis和Mybatis-Plus公用,但是公用有版本不兼容的問題,本文主要介紹了Spring Boot項(xiàng)目中同時(shí)集成Mybatis和Mybatis-plus,具有一檔的參考價(jià)值,感興趣的可以了解一下2024-12-12

