Java多執行緒/併發08、中斷執行緒 interrupt()

唐大麥發表於2017-04-28

一個執行緒是否能讓另一個執行緒停止執行?除了執行緒同步互斥機制之外,還有兩種方法:

  1. 可以使用Thread.stop(), Thread.suspend(), Thread.resume()
    和Runtime.runFinalizersOnExit() 這些終止執行緒執行的方法 。但這些方法已經被廢棄(The method stop() from the type Thread is deprecated),使用它們是極端不安全的。
  2. Thread.interrupt() 方法是很好的選擇。
public class InterruptDemo {
    public static void main(String[] args) throws InterruptedException {
        Runnable r = new TestRunnable();
        Thread th1 = new Thread(r);
        th1.start();
        /*三秒後中斷執行緒th1*/
        Thread.sleep(3000);
        th1.interrupt();
    }
}
class TestRunnable implements Runnable {
    public void run() {
        while (true) {
            System.out.println("Thread is running...");

            long time = System.currentTimeMillis();// 獲取系統時間的毫秒數
            while((System.currentTimeMillis() - time < 1000)){
                /*程式迴圈執行1秒鐘,不同於sleep(1000)會阻塞程式。*/
            }
        }
    }
}

執行發現,執行緒th1並沒有預期中斷。
為什麼呢?
每一個執行緒都有一個屬性:中斷狀態(interrupted status) ,可以通過Thread.currentThread().isInterrupted() 來檢查這個布林型的中斷狀態。
當呼叫th1.interrupt()時,只是改變了執行緒th1的中斷狀態。要想真正讓執行緒th1中斷,只能是th1自己來實現任務控制。
在上面的程式中,把TestRunnable類中的while (true)修改為while (!Thread.currentThread().isInterrupted()),程式即可達到我們期望

interrupt無法修改正在阻塞狀態(如被Object.wait, Thread.join和Thread.sleep三種方法之一阻塞時)的執行緒。如果嘗試修改,會觸發異常:java.lang.InterruptedException
上面的程式把TestRunnable修改成:

class TestRunnable implements Runnable {
    public void run() {
        while (!Thread.currentThread().isInterrupted()) {
            System.out.println("Thread is running...");

            long time = System.currentTimeMillis();// 獲取系統時間的毫秒數
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                System.out.print(e.getMessage());
            }
        }
    }
}

執行幾秒便會報錯,因為當執行緒在Thread.sleep時,外部執行緒嘗試呼叫interrupt()修改它的中斷狀態(interrupted status) 。

Core Java中有這樣一句話:”沒有任何語言方面的需求要求一個被中斷的程式應該終止。中斷一個執行緒只是為了引起該執行緒的注意,被中斷執行緒可以決定如何應對中斷 “。
換言之,沒有任何人可以逼迫美女嫁給自己,告訴她“我要娶你”是你的事,至於嫁不嫁最終由她決定。

相關文章