Java多執行緒之執行緒中止

innoyiya發表於2019-01-16

shop()

Java中提供了shop()方法來中斷執行緒,但其過於暴力而被定義為過期方法。假如一條執行緒在修改一段資料時,且已經修改了一半,此時的你強行用shop()方法中斷該執行緒後,資料處於一半修改過、一半未修改的狀態,該資料就已經廢了(且不會有任何提示)。除非你清楚在幹什麼,否則不要使用shop()。

Java中推薦使用中斷:

public void Thread.interrupt() //中斷執行緒

public boolean Thread.isInterrupted()    //判斷是否被中斷

public static boolean Thread.interrupted()    //判斷是否被中斷,且清除當前中斷狀態

public static void main(String[] args) throws InterruptedException {
    Thread t1 = new Thread() {
    @Override
    public void run () {
        while (true) {
        Thread.yield();
        }
    }
};
    t1.start();
    Thread.sleep(2000);
    ti.interrupt();
}
複製程式碼

在這裡雖然呼叫了interrupt()方法,但該執行緒並不會停下。因為該方法只是設定了一箇中斷狀態,但該執行緒並未對此中斷狀態做出反應。

以下程式碼進行了對中斷狀態的處理。

public static void main(String[] args) throws InterruptedException {
    Thread t1 = new Thread() {
    @Override
    public void run () {
        while (true) {
            if (Thread.currentThread().isInterrupted()){     //此方法返回中斷狀態,且不會清除該中斷狀態。
            System.out.println("Interruted!");
            breadk;
            }
            Thread.yield();
        }
    }
};
    t1.start();
    Thread.sleep(2000);
    ti.interrupt();
}
複製程式碼

但我們使用wait() 或者 sleep() 方法時要注意下:

首先得了解下Thread.sleep()函式:

public static native void sleep(long millis) throws InterruptedException

當該執行緒休眠時如果中斷則會丟擲該錯誤,此異常非執行時異常,必須捕獲且處理。

public static void main(String[] args) throws InterruptedException {
    Thread t1 = new Thread() {
    @Override
    public void run () {
        while (true) {
            if (Thread.currentThread().isInterrupted()){
            //此方法返回中斷狀態,且不會清除該中斷狀態
            System.out.println("Interruted!");
            break;
            }
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                System.out.println("Interruted When Sleep");
                // 設定中斷狀態
                Thread.currentThread().interrupt();
            }
        Thread.yield();
        }
    }
};
    t1.start();
    Thread.sleep(2000);
    t1.interrupt();
}
複製程式碼

在catch語塊中本可以進行中斷退出,但我們沒這麼做,因為這樣會破壞資料一致性和完整性(和直接使用shop()用異曲同工之妙)。所以我們在異常處理中必須重新設定中斷狀態(因為此時丟擲異常後狀態會被清除),讓該執行緒完成工作後再退出。

相關文章