久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Java并發(fā)之線程中斷

 airen89 2019-01-29

     前面的幾篇文章主要介紹了線程的一些最基本的概念,,包括線程的間的沖突及其解決辦法,以及線程間的協(xié)作機(jī)制。本篇主要來(lái)學(xué)習(xí)下Java中對(duì)線程中斷機(jī)制的實(shí)現(xiàn),。在我們的程序中經(jīng)常會(huì)有一些不達(dá)到目的不會(huì)退出的線程,,例如:我們有一個(gè)下載程序線程,該線程在沒(méi)有下載成功之前是不會(huì)退出的,若此時(shí)用戶覺得下載速度慢,不想下載了,,這時(shí)就需要用到我們的線程中斷機(jī)制了,告訴線程,,你不要繼續(xù)執(zhí)行了,,準(zhǔn)備好退出吧。當(dāng)然,,線程在不同的狀態(tài)下遇到中斷會(huì)產(chǎn)生不同的響應(yīng),,有點(diǎn)會(huì)拋出異常,有的則沒(méi)有變化,,有的則會(huì)結(jié)束線程。本篇將從以下兩個(gè)方面來(lái)介紹Java中對(duì)線程中斷機(jī)制的具體實(shí)現(xiàn):

  • Java中對(duì)線程中斷所提供的API支持
  • 線程在不同狀態(tài)下對(duì)于中斷所產(chǎn)生的反應(yīng)

一,、Java中對(duì)線程中斷所提供的API支持
     在以前的jdk版本中,,我們使用stop方法中斷線程,但是現(xiàn)在的jdk版本中已經(jīng)不再推薦使用該方法了,,反而由以下三個(gè)方法完成對(duì)線程中斷的支持,。

public boolean isInterrupted()

public void interrupt()

public static boolean interrupted() 

每個(gè)線程都一個(gè)狀態(tài)位用于標(biāo)識(shí)當(dāng)前線程對(duì)象是否是中斷狀態(tài)。isInterrupted是一個(gè)實(shí)例方法,,主要用于判斷當(dāng)前線程對(duì)象的中斷標(biāo)志位是否被標(biāo)記了,,如果被標(biāo)記了則返回true表示當(dāng)前已經(jīng)被中斷,否則返回false,。我們也可以看看它的實(shí)現(xiàn)源碼:

public boolean isInterrupted() {
        return isInterrupted(false);
}
private native boolean isInterrupted(boolean ClearInterrupted);

底層調(diào)用的本地方法isInterrupted,,傳入一個(gè)boolean類型的參數(shù),用于指定調(diào)用該方法之后是否需要清除該線程對(duì)象的中斷標(biāo)識(shí)位,。從這里我們也可以看出來(lái),,調(diào)用isInterrupted并不會(huì)清除線程對(duì)象的中斷標(biāo)識(shí)位。

interrupt是一個(gè)實(shí)例方法,,該方法用于設(shè)置當(dāng)前線程對(duì)象的中斷標(biāo)識(shí)位,。

interrupted是一個(gè)靜態(tài)的方法,用于返回當(dāng)前線程是否被中斷,。

public static boolean interrupted() {
    return currentThread().isInterrupted(true);
}
private native boolean isInterrupted(boolean ClearInterrupted);

該方法用于判斷當(dāng)前線程是否被中斷,,并且該方法調(diào)用結(jié)束的時(shí)候會(huì)清空中斷標(biāo)識(shí)位。下面我們看看線程所處不同狀態(tài)下對(duì)于中斷操作的反應(yīng),。

二,、線程在不同狀態(tài)下對(duì)于中斷所產(chǎn)生的反應(yīng)
     線程一共6種狀態(tài),分別是NEW,,RUNNABLE,,BLOCKED,,WAITING,TIMED_WAITING,,TERMINATED(Thread類中有一個(gè)State枚舉類型列舉了線程的所有狀態(tài)),。下面我們就將把線程分別置于上述的不同種狀態(tài),然后看看我們的中斷操作對(duì)它們的影響,。

1,、NEW和TERMINATED
     線程的new狀態(tài)表示還未調(diào)用start方法,還未真正啟動(dòng),。線程的terminated狀態(tài)表示線程已經(jīng)運(yùn)行終止,。這兩個(gè)狀態(tài)下調(diào)用中斷方法來(lái)中斷線程的時(shí)候,Java認(rèn)為毫無(wú)意義,,所以并不會(huì)設(shè)置線程的中斷標(biāo)識(shí)位,,什么事也不會(huì)發(fā)生。例如:

public static void main(String[] args) throws InterruptedException {

    Thread thread = new MyThread();
    System.out.println(thread.getState());

    thread.interrupt();

    System.out.println(thread.isInterrupted());
}

輸出結(jié)果如下:

run

terminated狀態(tài):

public static void main(String[] args) throws InterruptedException {

     Thread thread = new MyThread();
     thread.start();

     thread.join();
     System.out.println(thread.getState());

     thread.interrupt();

    System.out.println(thread.isInterrupted());

}

輸出結(jié)果如下:

這里寫圖片描述

從上述的兩個(gè)例子來(lái)看,,對(duì)于處于new和terminated狀態(tài)的線程對(duì)于中斷是屏蔽的,,也就是說(shuō)中斷操作對(duì)這兩種狀態(tài)下的線程是無(wú)效的。

2,、RUNNABLE
     如果線程處于運(yùn)行狀態(tài),,那么該線程的狀態(tài)就是RUNNABLE,但是不一定所有處于RUNNABLE狀態(tài)的線程都能獲得CPU運(yùn)行,,在某個(gè)時(shí)間段,,只能由一個(gè)線程占用CPU,那么其余的線程雖然狀態(tài)是RUNNABLE,,但是都沒(méi)有處于運(yùn)行狀態(tài),。而我們處于RUNNABLE狀態(tài)的線程在遭遇中斷操作的時(shí)候只會(huì)設(shè)置該線程的中斷標(biāo)志位,并不會(huì)讓線程實(shí)際中斷,,想要發(fā)現(xiàn)本線程已經(jīng)被要求中斷了則需要用程序去判斷,。例如:

/*先定義一個(gè)線程類*/
public class MyThread extends Thread{

    @Override
    public void run(){
        while(true){
            //do something
        }
    }
}
/*main函數(shù)啟動(dòng)線程*/
public static void main(String[] args) throws InterruptedException {

    Thread thread = new MyThread();
    thread.start();

    System.out.println(thread.getState());

    thread.interrupt();
    Thread.sleep(1000);//等到thread線程被中斷之后
    System.out.println(thread.isInterrupted());

    System.out.println(thread.getState());
}

我們定義的線程始終循環(huán)做一些事情,主線程啟動(dòng)該線程并輸出該線程的狀態(tài),,然后調(diào)用中斷方法中斷該線程并再次輸出該線程的狀態(tài),。總的輸出結(jié)果如下:

這里寫圖片描述

可以看到在我們啟動(dòng)線程之后,,線程狀態(tài)變?yōu)镽UNNABLE,,中斷之后輸出中斷標(biāo)志,顯然中斷位已經(jīng)被標(biāo)記,,但是當(dāng)我們?cè)俅屋敵鼍€程狀態(tài)的時(shí)候發(fā)現(xiàn),,線程仍然處于RUNNABLE狀態(tài)。很顯然,,處于RUNNBALE狀態(tài)下的線程即便遇到中斷操作,,也只會(huì)設(shè)置中斷標(biāo)志位并不會(huì)實(shí)際中斷線程運(yùn)行,。那么問(wèn)題是,既然不能直接中斷線程,,我要中斷標(biāo)志有何用處,?
這里其實(shí)Java將這種權(quán)力交給了我們的程序,Java給我們提供了一個(gè)中斷標(biāo)志位,,我們的程序可以通過(guò)if判斷中斷標(biāo)志位是否被設(shè)置來(lái)中斷我們的程序而不是系統(tǒng)強(qiáng)制的中斷,。例如:

/*修改MyThread類的run方法*/
public void run(){
    while(true){
        if (Thread.currentThread().isInterrupted()){
            System.out.println("exit MyThread");
            break;
        }
    }
}

線程一旦發(fā)現(xiàn)自己的中斷標(biāo)志為被設(shè)置了,立馬跳出死循環(huán),。這樣的設(shè)計(jì)好處就在于給了我們程序更大的靈活性,。

3、BLOCKED
     當(dāng)線程處于BLOCKED狀態(tài)說(shuō)明該線程由于競(jìng)爭(zhēng)某個(gè)對(duì)象的鎖失敗而被掛在了該對(duì)象的阻塞隊(duì)列上了,。那么此時(shí)發(fā)起中斷操作不會(huì)對(duì)該線程產(chǎn)生任何影響,,依然只是設(shè)置中斷標(biāo)志位。例如:

/*自定義線程類*/
public class MyThread extends Thread{

    public synchronized static void doSomething(){
        while(true){
            //do something
        }
    }
    @Override
    public void run(){
        doSomething();
    }
}

這里我們自定義了一個(gè)線程類,,run方法中主要就做一件事情,,調(diào)用一個(gè)有鎖的靜態(tài)方法,該方法內(nèi)部是一個(gè)死循環(huán)(占用該鎖讓其他線程阻塞),。

public static void main(String[] args) throws InterruptedException {

    Thread thread1 = new MyThread();
    thread1.start();

    Thread thread2 = new MyThread();
    thread2.start();

    Thread.sleep(1000);
    System.out.println(thread1.getState());
    System.out.println(thread2.getState());

    thread2.interrupt();
    System.out.println(thread2.isInterrupted());
    System.out.println(thread2.getState());
}

在我們的主線程中,我們定義了兩個(gè)線程并按照定義順序啟動(dòng)他們,,顯然thread1啟動(dòng)后便占用MyThread類鎖,,此后thread2在獲取鎖的時(shí)候一定失敗,自然被阻塞在阻塞隊(duì)列上,,而我們對(duì)thread2進(jìn)行中斷,,輸出結(jié)果如下:

這里寫圖片描述

從輸出結(jié)果看來(lái),thread2處于BLOCKED狀態(tài),,執(zhí)行中斷操作之后,,該線程仍然處于BLOCKED狀態(tài),但是中斷標(biāo)志位卻已被修改,。這種狀態(tài)下的線程和處于RUNNABLE狀態(tài)下的線程是類似的,,給了我們程序更大的靈活性去判斷和處理中斷。

4,、WAITING/TIMED_WAITING
     這兩種狀態(tài)本質(zhì)上是同一種狀態(tài),,只不過(guò)TIMED_WAITING在等待一段時(shí)間后會(huì)自動(dòng)釋放自己,而WAITING則是無(wú)限期等待,,需要其他線程調(diào)用notify方法釋放自己,。但是他們都是線程在運(yùn)行的過(guò)程中由于缺少某些條件而被掛起在某個(gè)對(duì)象的等待隊(duì)列上。當(dāng)這些線程遇到中斷操作的時(shí)候,,會(huì)拋出一個(gè)InterruptedException異常,,并清空中斷標(biāo)志位,。例如:

/*定義一個(gè)線程類*/
public class MyThread extends Thread{

    @Override
    public void run(){
        synchronized (this){
            try {
                wait();
            } catch (InterruptedException e) {
                System.out.println("i am waiting but facing interruptexception now");
            }
        }
    }
}

我們定義了一個(gè)線程類,其中run方法讓當(dāng)前線程阻塞到條件隊(duì)列上,,并且針對(duì)InterruptedException 進(jìn)行捕獲,,如果遇到InterruptedException 異常則輸出一行信息。

/*main函數(shù)啟動(dòng)該線程*/
public static void main(String[] args) throws InterruptedException {

    Thread thread = new MyThread();
    thread.start();

    Thread.sleep(500);
    System.out.println(thread.getState());
    thread.interrupt();
    Thread.sleep(1000);
    System.out.println(thread.isInterrupted());
}

在main線程中我們啟動(dòng)一個(gè)MyThread線程,,然后對(duì)其進(jìn)行中斷操作,。

這里寫圖片描述

從運(yùn)行結(jié)果看,當(dāng)前程thread啟動(dòng)之后就被掛起到該線程對(duì)象的條件隊(duì)列上,,然后我們調(diào)用interrupt方法對(duì)該線程進(jìn)行中斷,,輸出了我們?cè)赾atch中的輸出語(yǔ)句,顯然是捕獲了InterruptedException異常,,接著就看到該線程的中斷標(biāo)志位被清空,。

綜上所述,我們分別介紹了不同種線程的不同狀態(tài)下對(duì)于中斷請(qǐng)求的反應(yīng),。NEW和TERMINATED對(duì)于中斷操作幾乎是屏蔽的,,RUNNABLE和BLOCKED類似,對(duì)于中斷操作只是設(shè)置中斷標(biāo)志位并沒(méi)有強(qiáng)制終止線程,,對(duì)于線程的終止權(quán)利依然在程序手中,。WAITING/TIMED_WAITING狀態(tài)下的線程對(duì)于中斷操作是敏感的,他們會(huì)拋出異常并清空中斷標(biāo)志位,。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多