1. 程式人生 > >Java線程中斷

Java線程中斷

oid bject catch 技術分享 except top logs 自己 .com

線程中斷:

首先線程在未正常結束之前,被強制終止是很危險的事,會造成意想不到的後果。

但有時想讓一個線程結束,或者結束某種等待的狀態,該咋辦?

使用等待/通知機制或者給那個線程一個中斷信號,讓它自己決定該怎麽辦?


中斷使用的場景:

  1.線程為了等待一些特定的資源的到來,調用了Thread.sleep(10000), 讓自己10秒後醒過來,但是如果這些特定條件提前到來,來通知處於sleep狀態的線程,“嘿老兄,別再睡了”。

  2.線程通過調用子線程的join方法阻塞自己等待子線程結束,但是子線程運行過程中發現自己在短時間內沒法結束,所以它要通知主線程,別再等待子線程了。

  這些情況下,就需要中斷。


中斷的函數:

  

  Thread.interrupt()方法來做的。

  比如A線程調用了這個方法,這個方法就修改了A線程的中斷狀態。

  在非阻塞的線程中

  這個方法修改中斷狀態只是改變了線程中的一個布爾變量的值,在線程體run()方法中調用Thread.CurrendThread().isInterrupt()這個方法,會返回一個true

  在可取消阻塞狀態的線程中,比如線程run()方法內調用了Thread.sleep()Thread.join()Object.wait()這些方法的線程處於等待的過程中。這個線程調用了interrupt()方法,然後這個線程的Thread.CurrendThread().isInterrupt()

的值會改變成true。這個線程收到中斷信號後,會拋出InterruptedException異常。

非阻塞狀態的線程中:

public class Interrupt {
    public static void main(String[] args) {
       // Interrupt interrupt=new Interrupt();
        ThreadC threadC=new ThreadC();
        threadC.start();
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        threadC.interrupt();
    }
}
class ThreadC extends Thread{
    public void run(){

        while(true){
            if (Thread.currentThread().isInterrupted()){
                System.out.println("Someone interrupt me");
            }else{
                System.out.println("Thread is Going ...");
            }
        }
    }
}

運行結果: 

技術分享圖片

技術分享圖片

結果分析:

  main方法中線程threadC 開始執行,threadC線程此時沒有被中斷,不斷輸出 Thread is Going

  在main線程睡眠3秒結束後,執行了threadC.interrupt()方法,中斷線程,此時Thread.currentThread().isInterrupted()的值成為了true。但是線程卻不會停止,會不斷的輸出Someone interrupt me,它只是被修改了一個中斷信號。

  當在main方法中調用threadC.interrupt()方法的時候,線程threadC的中斷狀態(interrupted status )會被置位,然後在線程體內通過Thread.currentThread().isInterrupted()來檢查這個布爾變量的中斷狀態。

阻塞狀態的線程:

public class Interrupt {
    public static void  ThreadD threadD=new ThreadD();
        threadD.start();
        System.out.println("線程開始執行");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("中斷線程");
        threadD.interrupt();


    }
}

class ThreadD extends Thread{
    boolean  stop=false;
    public void run(){
//        while(!stop){
//            System.out.println("Thread is Going ...");
//        }
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            System.out.println("線程睡眠被中斷");
        }

        System.out.println("線程繼續執行...");
    }
} main(String[] args) {

運行結果:

技術分享圖片

結果分析:

如果線程被Object.warit()Thread.sleep()Thread.join()方法阻塞,調用該線程的interrupt()方法的時候會 拋出InterruptException異常,從而提早的結束阻塞狀態。

線程睡眠3秒,main方法睡眠2秒後執行threadD.interrupt()方法。此時線程會拋出異常,結束睡眠。


其它:

  不是所有阻塞方法收到中斷後都可以取消阻塞狀態,輸入和輸出類會阻塞等待IO完成,但是它們不會拋出interruptedException,而且在被中斷的時候也不會退出阻塞狀態。

  synchronized在獲鎖的過程中是不能被中斷的。

但是 ReentrantLock 支持可中斷的獲取模式即 tryLock(long time, TimeUnit unit)

Java線程中斷