Java中線程中斷的幾種方法小結(jié)
使用線程的stop()來(lái)中斷線程
這種方式是直接調(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()來(lái)中斷線程
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ì)一直無(wú)限執(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();
}

程序并沒(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線程啟動(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()方法
判斷線程是否被中斷并清除當(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)前線程是否被中斷(通過(guò)檢查中斷標(biāo)志位)并獲得中斷標(biāo)志 - public static boolean interrupted() . 該方法是Thread類(lèi)的靜態(tài)方法
返回當(dāng)前線程的中斷狀態(tài)真實(shí)值后會(huì)將當(dāng)前線程的中斷狀態(tài)設(shè)置為false,此方法調(diào)用之后會(huì)清除當(dāng)前線程的中斷標(biāo)志位的狀態(tài)。
通過(guò)共享變量來(lái)控制
1.使用volatile 關(guān)鍵字來(lái)實(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來(lái)實(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 來(lái)實(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)文章
使用Idea快速搭建SpringMVC項(xiàng)目的詳細(xì)步驟記錄
這篇文章主要給大家介紹了關(guān)于使用Idea快速搭建SpringMVC項(xiàng)目的詳細(xì)步驟,Spring?MVC是一種基于MVC模式的框架,它是Spring框架的一部分,它提供了一種更簡(jiǎn)單和更有效的方式來(lái)構(gòu)建Web應(yīng)用程序,需要的朋友可以參考下2024-05-05
httpclient ConnectionHolder連接池連接保持源碼解析
這篇文章主要為大家介紹了httpclient ConnectionHolder連接池連接保持源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11
基于springboot+vue實(shí)現(xiàn)垃圾分類(lèi)管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了基于springboot+vue實(shí)現(xiàn)垃圾分類(lèi)管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-07-07
mybatis調(diào)用存儲(chǔ)過(guò)程的實(shí)例代碼
這篇文章主要介紹了mybatis調(diào)用存儲(chǔ)過(guò)程的實(shí)例,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-10-10
spring boot整合redis實(shí)現(xiàn)shiro的分布式session共享的方法
本篇文章主要介紹了spring boot整合redis實(shí)現(xiàn)shiro的分布式session共享的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-01-01
Java實(shí)現(xiàn)簡(jiǎn)單控制臺(tái)版ATM系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)簡(jiǎn)單控制臺(tái)版ATM系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05
java實(shí)現(xiàn)音頻轉(zhuǎn)文本的實(shí)現(xiàn)步驟
本文主要介紹了java實(shí)現(xiàn)音頻轉(zhuǎn)文本的實(shí)現(xiàn)步驟,可以通過(guò)使用一些現(xiàn)成的庫(kù)或者API來(lái)實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-05-05

