1. 程式人生 > 其它 >Java 執行緒中斷相關方法:interrupt() isInterrupted() interrupted()

Java 執行緒中斷相關方法:interrupt() isInterrupted() interrupted()

interrupt() 方法只是改變中斷狀態而已,它不會中斷一個正在執行的執行緒。如果執行緒被Object.wait, Thread.join和Thread.sleep三種方法之一阻塞,此時呼叫該執行緒的interrupt()方法,那麼該執行緒將丟擲一個 InterruptedException中斷異常。

使用stop方法雖然可以強行終止正在執行或掛起的執行緒,但使用stop方法是很危險的,可能會產生不可預料的結果,因此,並不推薦使用stop方法來終止執行緒。Thread.interrupt()方法: 作用是中斷執行緒。將會設定該執行緒的中斷狀態位,即設定為true,中斷的結果執行緒是死亡、還是等待新的任務或是繼續執行至下一步,就取決於這個程式本身。執行緒會不時地檢測這個中斷標示位,以判斷執行緒是否應該被中斷(中斷標示值是否為true)。它並不像stop方法那樣會中斷一個正在執行的執行緒 interrupt()方法只是改變中斷狀態,不會中斷一個正在執行的執行緒。

Java虛擬機器對會丟擲InterruptedException異常的方法進行了特別處理:Java虛擬機器會將該執行緒的中斷標誌位清除,然後丟擲InterruptedException,這個時候呼叫isInterrupted方法返回的也是false。

一旦執行緒的中斷狀態被置為“中斷狀態”,就會丟擲中斷異常。

(1)interrupt:置執行緒的中斷狀態。

(2)isInterrupted:測試執行緒(*呼叫該方法的執行緒*)是否已經中斷,不清除中斷狀態。

(3)interrupted:測試當前執行緒(當前執行緒是指執行interrupted()方法的執行緒)是否已經中斷,且清除中斷狀態。

看原始碼可以得知:interrupted方法底層就是呼叫了清除標誌位的isInterrupted方法。

public boolean isInterrupted() {
    return isInterrupted(false);
}

private native boolean isInterrupted(boolean ClearInterrupted);

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

演示demo:

public class Test {

    public static void main(String[] args) {
/*        testWait();
        佔有鎖
        interrupt標誌位: false
        interrupt標誌位: true
        執行緒中斷*/
        
/*        testSleep();
        interrupt標誌位: false
        interrupt標誌位: true
        執行緒testSleepTread中斷*/
        
/*      testJoin();
        Task is interrupted*/
    }

    public static void testSleep() {
        Runnable testSleepTread = () -> {
            try {
                Thread.sleep(1000 * 50);
            } catch (InterruptedException e) {
                System.out.println("執行緒testSleepTread中斷");
            }
        };
        Thread thread1 = new Thread(testSleepTread);
        thread1.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("interrupt標誌位: " + thread1.isInterrupted());
        thread1.interrupt();
        System.out.println("interrupt標誌位: " + thread1.isInterrupted());
    }

    public static void testWait() {
        Object lock = new Object();
        Runnable testWaitTread = () -> {
            synchronized (lock) {
                System.out.println("佔有鎖");
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    System.out.println("執行緒中斷");
                }
            }
        };
        Thread threadHasLock = new Thread(testWaitTread);
        threadHasLock.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("interrupt標誌位: " + threadHasLock.isInterrupted());
        threadHasLock.interrupt();
        System.out.println("interrupt標誌位: " + threadHasLock.isInterrupted());
    }

    public static void testJoin() {
        Thread thread1 = new Thread(new Task());
        thread1.start();
        try {
            thread1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    static class Task implements Runnable {
        @Override
        public void run() {
            try {
                Thread.currentThread().interrupt();
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                System.out.println("Task is interrupted");
            }
        }
    }

}