日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

Java线程中断机制-如何中断线程

發(fā)布時間:2025/3/15 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java线程中断机制-如何中断线程 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Java線程中斷機制-如何中斷線程

?版權(quán)聲明:本文為博主原創(chuàng)文章,歡迎指正或者轉(zhuǎn)載。 https://blog.csdn.net/qq_38663729/article/details/78232648

介紹:

對于線程一共分為五個狀態(tài):新建狀態(tài),就緒狀態(tài),阻塞狀態(tài),運行狀態(tài),死亡狀態(tài),有時候把阻塞狀態(tài)又分為同步阻塞和等待阻塞。


有時想讓主線程啟動的一個子線程結(jié)束運行,我們就需要讓這個子線程中斷,不再繼續(xù)執(zhí)行。線程是有中斷機制的,我們可以對每個線程進行中斷標記,注意只是標記,中斷與否還是虛擬機自己的事情,虛擬機自己家的事情,我們也就說說,不能實際操作控制他家。java中的Thread類是一個對線程進行操作的類,提供了中斷線程的方法interrupt(),在API中是這么定義的(中文的翻譯可能不準確)。

在Thread中其實還有一個stop()方法也是中斷線程的方法,但是這個方法太粗魯了,人家好好的線程正在運行,只要調(diào)用了stop()方法,線程就會中斷,不管是在進行什么操作。這個方法已經(jīng)被廢棄,他的執(zhí)行會帶來一些不可確定的狀況。

線程可以調(diào)用中斷自己的方法interrupt()方法,但是中斷也是有條件的,在線程調(diào)用interrupt()方法的時候虛擬機會在此線程上標記一個標志(這個中斷標志只是一個布爾類型的變量),代表這個線程可能被中斷,在后面的中斷操作也是根據(jù)這個中斷標志執(zhí)行的。可以說interrupt()方法是一種友好的方法,總是和虛擬機商量著來。如果一個線程處于了阻塞狀態(tài)(如線程調(diào)用了sleep()、join()、wait()、以及可中斷的通道上的 I/O 操作方法后可進入阻塞狀態(tài)),則在線程在檢查中斷標示時如果發(fā)現(xiàn)中斷標示為true,則會在這些阻塞方法(sleep()、join()、wait()及可中斷的通道上的 I/O 操作方法)調(diào)用處拋出InterruptedException異常,并且在拋出異常后立即將線程的中斷標示位清除,即重新設(shè)置為false。拋出異常是為了線程從阻塞狀態(tài)醒過來,并在結(jié)束線程前讓程序員有足夠的時間來處理中斷請求。

線程的一些狀態(tài)都可能影響到這個中斷標記從而結(jié)束中斷。下面這個例子驗證中斷標志被除掉的說法

package demo_thread;

public class Interrupt {

?public static void main(String[] args) {

? ?A a = new A();

? ?Thread t1 = new Thread(a);

? ?t1.start();

? ?t1.interrupt();

? ?System.out.println("執(zhí)行睡眠之前1:"+t1.isInterrupted());

? ?try {

? ? ?System.out.println("執(zhí)行睡眠之前2:"+t1.isInterrupted());

? ? ?t1.sleep(1000);//線程進入阻塞狀態(tài)

? ?} catch (InterruptedException e) {

? ? ?e.printStackTrace();

? ?}finally {

? ? System.out.println("執(zhí)行睡眠之后:"+t1.isInterrupted());

? ?}

?}

}

class A implements Runnable{

?@Override

?public void run() {

? ?System.out.println(Thread.currentThread());

?}

}

在main方法中創(chuàng)建一個線程,線程中重寫的run()方法輸出線程號,只是一個顯示分隔,具體看在執(zhí)行讓線程阻塞方法之前和之后線程的中斷標記。isInterrupted()方法是判斷線程是否執(zhí)行中斷的方法,就是判斷中斷標記是否存在的方法。

輸出:

執(zhí)行睡眠之前1:true 執(zhí)行睡眠之前2:true Thread[Thread-0,5,main] 執(zhí)行睡眠之后:false

可以看到只要執(zhí)行了sleep()方法,線程的中斷標記就會被清除。分別調(diào)用執(zhí)行了join()、wait()方法,可以看到他們的共同點都是需要捕獲一個InterruptedException,在調(diào)用join()方法的時候得到了和sleep()方法一樣的輸出結(jié)果,但是在調(diào)用wait()方法的時候,雖然在后面調(diào)用notify()方法,但是是否獲得執(zhí)行權(quán)限還是無法預料的。

中斷一個線程只是為了引起該線程的注意,被中斷線程可以決定如何應(yīng)對中斷,中斷或者不中斷。某些線程非常重要,以至于它們應(yīng)該不理會中斷,而是在處理完拋出的異常之后繼續(xù)執(zhí)行,但是更普遍的情況是,一個線程將把中斷看作一個終止請求。

兩個很像的方法的區(qū)別:

interrupted():測試當前線程是否中斷。 該方法可以清除線程的中斷狀態(tài) 。換句話說,如果這個方法被連續(xù)調(diào)用兩次,那么第二個調(diào)用將返回false(除非當前線程再次中斷,在第一個調(diào)用已經(jīng)清除其中斷狀態(tài)之后,在第二個調(diào)用之前已經(jīng)檢查過)。

isInterrupted():測試這個線程是否被中斷。線程的中斷狀態(tài)不受此方法的影響。

如何中斷線程:


接下來看請求中斷之后發(fā)生的事情:在網(wǎng)上看到一個例子

package demo_thread;

?public class Interrupt {

? ?public static void main(String[] args) {

? ? ?try {

? ? ? MyThread thread = new MyThread();

? ? ? thread.start();

? ? ? Thread.sleep(2000);

? ? ? thread.interrupt();//請求中斷MyThread線程

? ? ?} catch (Exception e) {

? System.out.println("main catch");

e.printStackTrace();

}

System.out.println("end!");

}

}

class MyThread extends Thread {

?@Override

?public void run() {

? ?super.run();

? ?for (int i = 0; i < 500000; i++) {

? ? ?if (this.interrupted()) {

? ? ? ?System.out.println("should be stopped and exit");

? ? ? ?break;

? ? ?}

? ? System.out.println("i=" + (i + 1));

? ?}

? //盡管線程被中斷,但并沒有結(jié)束運行。這行代碼還是會被執(zhí)行

? System.out.println("this line is also executed. thread does not stopped");

? }

}
在文章的開頭處已經(jīng)說了,線程執(zhí)行中斷方法,只是給線程一個中斷標記,是否中斷是他自己的事

其中一次的輸出:

…… i=75722 end! should be stopped and exit this line is also executed. thread does not stopped


由于線程執(zhí)行了sleep()方法,進入阻塞狀態(tài),所以在從阻塞狀態(tài)從新回到運行狀態(tài)的時候,發(fā)現(xiàn)自己已經(jīng)有了中斷標記,執(zhí)行if中的語句,線程的睡眠和執(zhí)行總是和計算機內(nèi)部有關(guān)系,所以每次輸出的結(jié)束數(shù)字總是不一樣的。

通過輸出結(jié)果我們發(fā)現(xiàn)一個很重要的問題,我們要的是線程的中斷,也就是關(guān)于線程的方法需要停止執(zhí)行,但是在循環(huán)外面的輸出語句也執(zhí)行了,這個中斷只是中斷了循環(huán)的執(zhí)行。


那么我們應(yīng)該怎么中斷線程呢?利用線程中斷異常就是一個很好的辦法,既然是異常,通常異常可以中斷線程的運行,使程序掛掉,我們自己拋出一個異常讓線程中斷

class MyThread extends Thread {

? ? ? @Override

? ? ? public void run() {

? ? ? ?super.run();

? ? ? ?try {

? ? ? ? ?for (int i = 0; i < 500000; i++) {

? ? ? ? ? ?if (this.interrupted()) {

? ? ? ? ? ? ?System.out.println("should be stopped and exit");

? ? ? ? ? ? ?throw new InterruptedException();

? ? ? ? ? ? }

? ? ? ? ? System.out.println("i=" + (i + 1));

? ? ? ? ?}

? ? System.out.println("this line cannot be executed. cause thread throws exception");//這行語句不會被執(zhí)行!!!

? ? ? ?} catch (InterruptedException e) {

? ? ? ? ? System.out.println("catch interrupted exception");

? ? ? ? ? e.printStackTrace();

? ? ?}

? }

}
輸出:

…… i=131892 should be stopped and exit end!


但是通過拋出異常也帶來了問題,我們不能通過拋出異常來處理問題,還需要在捕獲異常的代碼中加上處理的語句,例如保存用戶的操作等等,讓這次中斷看起來是很正常的中斷。
我們還可以通過讓程序主動拋出異常,在線程阻塞的時候,執(zhí)行中斷操作,拋出異常,在循環(huán)中循環(huán)打印當前時間,

package demo_thread;

import java.text.SimpleDateFormat;

import java.util.Date;

public class SleepInterruptTest {

?public static void main(String[] args) {

? ? SleepThread t1 = new SleepThread();

? ? t1.start();

? ? try {

? ? ? Thread.sleep(5000);

? ? } catch (InterruptedException e) {

? ? ? e.printStackTrace();

? ? }

? ?t1.interrupt();//主動打斷線程,使SleepThread線程拋出異常

? }

}

class SleepThread extends Thread{

? ? public void run(){

? ? ? while(true){

? ? ? ?try{

? ? ? ? ?SimpleDateFormat sim = new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss");

? ? ? ? ?System.out.println(sim.format(new Date()));

? ? ? ? ?sleep(1000);

? ? ? ? }

? ? ? ?catch(InterruptedException e){

? ? ? ?System.out.println("線程中斷");

? ? ? ?return;

? ? }

? ?}

? ?}

}

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎

總結(jié)

以上是生活随笔為你收集整理的Java线程中断机制-如何中断线程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。