Java中終止線程的方法詳解
Java中終止線程的方式主要有三種:
1、使用stop()方法,已被棄用。原因是:stop()是立即終止,會(huì)導(dǎo)致一些數(shù)據(jù)被到處理一部分就會(huì)被終止,而用戶并不知道哪些數(shù)據(jù)被處理,哪些沒(méi)有被處理,產(chǎn)生了不完整的“殘疾”數(shù)據(jù),不符合完整性,所以被廢棄。So, forget it!
2、使用volatile標(biāo)志位
看一個(gè)簡(jiǎn)單的例子:
首先,實(shí)現(xiàn)一個(gè)Runnable接口,在其中定義volatile標(biāo)志位,在run()方法中使用標(biāo)志位控制程序運(yùn)行
public class MyRunnable implements Runnable {
//定義退出標(biāo)志,true會(huì)一直執(zhí)行,false會(huì)退出循環(huán)
//使用volatile目的是保證可見(jiàn)性,一處修改了標(biāo)志,處處都要去主存讀取新的值,而不是使用緩存
public volatile boolean flag = true;
public void run() {
System.out.println("第" + Thread.currentThread().getName() + "個(gè)線程創(chuàng)建");
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
//退出標(biāo)志生效位置
while (flag) {
}
System.out.println("第" + Thread.currentThread().getName() + "個(gè)線程終止");
}
}
然后,在main()方法中創(chuàng)建線程,在合適的時(shí)候,修改標(biāo)志位,終止運(yùn)行中的線程。
public class TreadTest {
public static void main(String[] arg) throws InterruptedException {
MyRunnable runnable = new MyRunnable();
//創(chuàng)建3個(gè)線程
for (int i = 1; i <= 3; i++) {
Thread thread = new Thread(runnable, i + "");
thread.start();
}
//線程休眠
Thread.sleep(2000L);
System.out.println("——————————————————————————");
//修改退出標(biāo)志,使線程終止
runnable.flag = false;
}
}
最后,運(yùn)行結(jié)果,如下:
第1個(gè)線程創(chuàng)建 第2個(gè)線程創(chuàng)建 第3個(gè)線程創(chuàng)建 -------------------------- 第3個(gè)線程終止 第1個(gè)線程終止 第2個(gè)線程終止
3、使用interrupt()中斷的方式,注意使用interrupt()方法中斷正在運(yùn)行中的線程只會(huì)修改中斷狀態(tài)位,可以通過(guò)isInterrupted()判斷。如果使用interrupt()方法中斷阻塞中的線程,那么就會(huì)拋出InterruptedException異常,可以通過(guò)catch捕獲異常,然后進(jìn)行處理后終止線程。有些情況,我們不能判斷線程的狀態(tài),所以使用interrupt()方法時(shí)一定要慎重考慮。
第一種:正在運(yùn)行中終止
public class MyThread extends Thread {
public void run(){
super.run();
try {
for(int i=0; i<500000; i++){
if(this.interrupted()) {
System.out.println("線程已經(jīng)終止, for循環(huán)不再執(zhí)行");
throw new InterruptedException();
}
System.out.println("i="+(i+1));
}
System.out.println("這是for循環(huán)外面的語(yǔ)句,也會(huì)被執(zhí)行");
} catch (InterruptedException e) {
System.out.println("進(jìn)入MyThread.java類(lèi)中的catch了。。。");
e.printStackTrace();
}
}
}
public class Run {
public static void main(String args[]){
Thread thread = new MyThread();
thread.start();
try {
Thread.sleep(2000);
thread.interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
運(yùn)行結(jié)果如下:
... i=203798 i=203799 i=203800 線程已經(jīng)終止, for循環(huán)不再執(zhí)行 進(jìn)入MyThread.java類(lèi)中的catch了。。。 java.lang.InterruptedException at thread.MyThread.run(MyThread.java:13)
第二種:阻塞狀態(tài)(sleep,wait等)終止
public class MyThread extends Thread {
public void run(){
super.run();
try {
System.out.println("線程開(kāi)始。。。");
Thread.sleep(200000);
System.out.println("線程結(jié)束。");
} catch (InterruptedException e) {
System.out.println("在沉睡中被停止, 進(jìn)入catch, 調(diào)用isInterrupted()方法的結(jié)果是:" + this.isInterrupted());
e.printStackTrace();
}
}
}
線程開(kāi)始。。。 在沉睡中被停止, 進(jìn)入catch, 調(diào)用isInterrupted()方法的結(jié)果是:false java.lang.InterruptedException: sleep interrupted at java.lang.Thread.sleep(Native Method) at thread.MyThread.run(MyThread.java:12)
從打印的結(jié)果來(lái)看, 如果在sleep狀態(tài)下停止某一線程,會(huì)進(jìn)入catch語(yǔ)句,并且清除停止?fàn)顟B(tài)值,使之變?yōu)閒alse。
前一個(gè)實(shí)驗(yàn)是先sleep然后再用interrupt()停止,與之相反的操作在學(xué)習(xí)過(guò)程中也要注意:
public class MyThread extends Thread {
public void run(){
super.run();
try {
System.out.println("線程開(kāi)始。。。");
for(int i=0; i<10000; i++){
System.out.println("i=" + i);
}
Thread.sleep(200000);
System.out.println("線程結(jié)束。");
} catch (InterruptedException e) {
System.out.println("先停止,再遇到sleep,進(jìn)入catch異常");
e.printStackTrace();
}
}
}
public class Run {
public static void main(String args[]){
Thread thread = new MyThread();
thread.start();
thread.interrupt();
}
}
運(yùn)行結(jié)果:
i=9998 i=9999 先停止,再遇到sleep,進(jìn)入catch異常 java.lang.InterruptedException: sleep interrupted at java.lang.Thread.sleep(Native Method) at thread.MyThread.run(MyThread.java:15)
感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!
相關(guān)文章
java面向?qū)ο缶幊填?lèi)的內(nèi)聚性分析
高內(nèi)聚、低耦合是軟件設(shè)計(jì)中非常關(guān)鍵的概念。在面向?qū)ο蟪绦蛟O(shè)計(jì)中類(lèi)的劃分時(shí),類(lèi)的內(nèi)聚性越高,其封裝性越好,越容易復(fù)用2021-10-10
Java類(lèi)加載器和類(lèi)加載機(jī)制實(shí)例分析
這篇文章主要介紹了Java類(lèi)加載器和類(lèi)加載機(jī)制,結(jié)合實(shí)例形式分析了java類(lèi)加載器與類(lèi)加載機(jī)制原理、實(shí)現(xiàn)方法及相關(guān)操作技巧,需要的朋友可以參考下2019-07-07
java設(shè)計(jì)模式之簡(jiǎn)單工廠模式簡(jiǎn)述
這篇文章主要為大家詳細(xì)介紹了java設(shè)計(jì)模式之簡(jiǎn)單工廠模式,簡(jiǎn)單工廠模式的實(shí)質(zhì)是由一個(gè)工廠類(lèi)根據(jù)傳入的參數(shù),動(dòng)態(tài)決定應(yīng)該創(chuàng)建哪一個(gè)產(chǎn)品類(lèi)的實(shí)例,感興趣的小伙伴們可以參考一下2016-08-08
Spring Boot 中嵌入式 Servlet 容器自動(dòng)配置原理解析
這篇文章主要介紹了Spring Boot 中嵌入式 Servlet 容器自動(dòng)配置原理解析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11
使用SpringSecurity設(shè)置角色和權(quán)限的注意點(diǎn)
這篇文章主要介紹了使用SpringSecurity設(shè)置角色和權(quán)限的注意點(diǎn),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03
分享關(guān)于JAVA 中使用Preferences讀寫(xiě)注冊(cè)表時(shí)要注意的地方
這篇文章介紹了關(guān)于JAVA 中使用Preferences讀寫(xiě)注冊(cè)表時(shí)要注意的地方,有需要的朋友可以參考一下2013-08-08

