Java執行緒中斷與終止執行緒執行

梧留柒的部落格發表於2014-09-28

Java中啟動一個執行緒很容易,通常情況下我們都是等到任務執行結束後讓執行緒自行停止。但有時需要在任務正在執行時取消他們,使得執行緒快速結束。對此Java並沒有提供任何機制。但是我們可以通過Java提供的執行緒中斷機制來實現。

首先來看Thread類三個和中斷有關的方法:

public class Thread {
    // 發出一箇中斷請求,把標誌位設定為中斷狀態,不會終止執行緒執行。
    // 其他執行緒試圖呼叫該方法,會檢測是否有許可權中斷該執行緒(正常情況
    // 下不會存在許可權問題,這裡可以忽略)
    public void interrupt() { ... }

    // 檢測標誌位是否為中斷的狀態
    public boolean isInterrupted() { ... }

    // 清除當前執行緒的標誌位的中斷狀態,返回是否為中斷狀態
    public static boolean interrupted() { ... }

    ...
}

既然執行緒中斷不會終止執行緒的執行,那麼如何通過執行緒中斷來實現終止執行緒執行呢?

我們知道一些阻塞執行緒的方法會丟擲InterruptedException表示執行緒中斷髮生,在這種情況下就可以使用執行緒中斷來終止執行緒的執行:

public class TestInterrupt {

    public static void main(String[] args)
    {
        BlockingQueue<Object> ObjectQueue = new LinkedBlockingQueue<Object>();
        Consumer consumer = new Consumer(ObjectQueue);

        Thread t = new Thread(consumer);
        t.start();

        // 等待執行緒的啟動
        try
        {
            Thread.sleep(1000);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }

        // 中斷執行緒
        t.interrupt();
    }

}

class Consumer implements Runnable
{
    private final BlockingQueue<Object> ObjectQueue;
    public Consumer(BlockingQueue<Object> ObjectQueue)
    {
        if (ObjectQueue == null)
        {
            throw new IllegalArgumentException("messageQueue cannot be null");
        }

        this.ObjectQueue = ObjectQueue;
    }

    @Override
    public void run()
    {
        boolean isRunning = true;
        while (isRunning)
        {
            try
            {
                // take方法阻塞時會因為執行緒中斷丟擲中斷異常
                System.out.println(ObjectQueue.take());
            }
            catch (InterruptedException e)
            {
          // 一旦丟擲中斷異常,執行緒的中斷狀態就會被清除,這個時候呼叫
                // Thread的isInterrupted()方法返回的是false
                isRunning = false;
                System.out.println("Cancelled");
            }
        }
    }
}

很多工執行的服務程式的邏輯和上面的例子很類似,都可以使用這種方法來終止執行緒的執行。

相關文章