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"); } } } }
很多任務執行的服務程序的邏輯和上面的例子很類似,都可以使用這種方法來終止線程的運行。