要使任務和線程能安全可靠地停止,並不是一件很容易的事情,java沒有提供任何機制來安全地終止線程,那麼我們該怎麼辦呢?
下面我們先來了解一下java中的中斷機制:
java中斷機制是一種協作機制,也就是說在某個線程中對另一個線程調用interrupt()方法並不能直接終止該線程,需要被中斷的線程自己處理中斷請求
interrupted() 和 isInterrupted()的主要區別:
非靜態方法isInterrupted()用來查詢某線程的中斷狀態,且不會改變該線程的中斷狀態標識;
靜態方法interrupted()檢查中斷狀態時,中斷狀態會被清零(置為false)。
在下面的例子中,主線程通過調用t.interrupt()方法將線程t的中斷狀態設置為true,線程t可以在合適的時候調用interrupted()方法或isInterrupted()方法來檢測其中斷狀態並做相應處理:
package com.test; public class ThreadTest extends Thread { public void run() { while (true) { if (Thread.interrupted()) { System.out.println("Someone interrupted me."); break; } else { System.out.println("Going..."); } long now = System.currentTimeMillis(); while (System.currentTimeMillis() - now < 1000) { //讓循環持續一段時間,打印的輸出語句會少一些 } } } public static void main(String[] args) throws InterruptedException { ThreadTest t = new ThreadTest(); t.start(); Thread.sleep(3000); t.interrupt(); } }
結果如下:
Going... Going... Going... Someone interrupted me.
(1)對於非阻塞中的線程, 只是改變了中斷狀態, 即Thread.isInterrupted()將返回true;
(2)對於可取消的阻塞狀態中的線程, 比如等待在Thread.sleep(), Object.wait(), Thread.join(),這些函數上的線程, 這個線程收到中斷信號後, 會拋出InterruptedException, 同時會把中斷狀態置回為false.
下面這段程序會使得阻塞在Thread.join()方法上的主線程在收到中斷信號後結束:
package com.test; public class ThreadTest extends Thread { private Thread parent; public ThreadTest(Thread parent){ this.parent = parent; } public void run() { while (true) { System.out.println("sub thread is running..."); long now = System.currentTimeMillis(); while (System.currentTimeMillis() - now < 2000) { //讓循環持續一段時間,打印的輸出語句會少一些 } parent.interrupt(); } } public static void main(String[] args){ ThreadTest t = new ThreadTest(Thread.currentThread()); t.start(); try { t.join(); } catch (InterruptedException e) { System.out.println("Parent thread will die..."); } } }
結果如下:
sub thread is running... Parent thread will die... sub thread is running... sub thread is running... sub thread is running... sub thread is running...
從結果可以看出,線程t發出中斷請求後主線程結束(此時線程t仍在運行)