併發編程線程中斷和線程中斷標誌

轉發請聲明出處:http://blog.csdn.net/qq_24692041/article/details/78455131


線程中斷,interrupt方法

 先看代碼和輸出結果

 子線程代碼:

package com.example;

/**
 * Created by PICO-USER on 2017/11/6.
 */

public class ThreadA extends Thread {
 
    @Override
    public void run() {
        super.run();
        try{
            System.out.println("in ThreadA - about to sleep for 20 seconds :"+isInterrupted());
            Thread.sleep(20000);
            System.out.println("in ThreadA - wake up");
        }catch(InterruptedException e){
            System.out.println("in ThreadA - interrupted while sleeping");
            System.out.println("in ThreadA - interrupt status of threadA :"+isInterrupted());
            //處理完中斷異常後,返回到run()方法人口,
            //如果沒有return,線程不會實際被中斷,它會繼續打印下面的信息
          //  return;
        }
        System.out.println("in ThreadA - leaving normally");
    }
}

主線程代碼:

package com.example;

public class MyClass {

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

        ThreadA threadA = new ThreadA();
        threadA.start();

        //主線程休眠2秒,從而確保剛纔啓動的線程有機會執行一段時間
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("in main() - interrupting other thread");
        //中斷線程t
        threadA.interrupt();
        System.out.println("in main() - interrupt status of threadA :"+threadA.isInterrupted());
        System.out.println("in main() - leaving");
    }
}
輸出結果:


代碼和結果分析:

主程序中先啓動了線程A,此時線程A的run方法開始執行,打印完“in run() - about to sleep for 20 seconds”之後A進入休眠狀態,休眠20秒。此時主線程是在併發執行的,主線程休眠2秒,2秒過後主線程休眠結束,調用interrupt方法中斷A線程,並且主線程main方法執行完畢,所以主線程消亡。此時A線程本應該還在休眠狀態,但由於interrupt方法被調用,直接讓A線程結束了休眠狀態拋出了中斷異常,然後繼續執行try,catch後面的代碼,run方法走完之後消亡。這裏注意:如果在catch塊中return,那後面的代碼將不會繼續執行,因爲return代表run方法執行結束,A線程就直接消亡了。

重點:從上面的代碼可以看出interrupt方法的調用只是在目標線程中設置了中斷標誌爲true,代表該線程已經被中斷,並不會直接終止該線程注意看isInterrupt方法打印出來的結果,在A線程開始執行run方法的時候打印的是false,然後中斷A線程的一瞬間我們在主線程打印了A線程的中斷狀態是true,最後在A線程的catch塊中打印出來的卻是false,說明interrupt方法的調用的時候的確是設置了中斷標誌,並且沒有直接終止線程的執行。

當線程遇到阻塞,比如調用sleep,wait,join方法的時候,就會拋出中斷異常,並且重置中斷標誌。所以上面catch方法中的isInterrupt方法返回的是false。

最後說一點,其實上面我們在主線程打印A線程中斷標誌的時候有取巧的嫌疑,只是打印的位置哈,interrupt設置中斷標誌的結論肯定是沒錯的。因爲在主線程中打印A的中斷標誌的時候,有可能A的異常已經被拋出,並且重置了中斷標誌,那樣的結果就會是false。


方法判斷線程中斷

線程中斷判斷方法有兩個,一個是interrupted()方法,該方法是靜態方法,該方法是中斷當前線程並且該方法會將中斷標誌重置,另一個方法就是上面用到的isInterrupted()方法,這個方法是非靜態方法,作用於對象,返回的是目標線程的中斷標誌,本身並不會重置中斷標誌,需要線程阻塞,比如調用sleep,wait,join方法導致阻塞的時候,將中斷標誌重置。下面看看兩個示例代碼:

package com.example;

/**
 * Created by PICO-USER on 2017/11/6.
 */

public class ThreadB extends Thread {

    @Override
    public void run() {
        super.run();
        System.out.print("ThreadB isInterrupted :"+isInterrupted()+"\n");
        System.out.print("ThreadB interrupted :"+ThreadB.interrupted()+"\n");
        interrupt();
        System.out.print("ThreadB isInterrupted :"+isInterrupted()+"\n");
        System.out.print("ThreadB isInterrupted :"+isInterrupted()+"\n");
        System.out.print("ThreadB interrupted :"+ThreadB.interrupted()+"\n");
        System.out.print("ThreadB interrupted :"+ThreadB.interrupted()+"\n");
    }
}

package com.example;

public class MyClass {

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

        ThreadB threadB = new ThreadB();
        threadB.start();
        System.out.print("main :" + Thread.currentThread().isInterrupted() + "\n");
    }
}
運行結果:


很清楚的看到調用interrupt方法之後連續打印的兩次isInterrupted的返回值都是true,然而第一次調用interrupted方法的返回值是true,但是第二次調用的時候就已經被重置返回false了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章