用interrupt()中斷Java線程

from  http://hapinwater.iteye.com/blog/310558

最近在學習Java線程相關的東西,和大家分享一下,有錯誤之處歡迎大家指正.


假如我們有一個任務如下,交給一個Java線程來執行,如何才能保證調用interrupt()來中斷它呢?
Java代碼  收藏代碼
  1. class ATask implements Runnable{  
  2.   
  3.     private double d = 0.0;  
  4.       
  5.     public void run() {  
  6.         //死循環執行打印"I am running!" 和做消耗時間的浮點計算  
  7.         while (true) {  
  8.             System.out.println("I am running!");  
  9.               
  10.             for (int i = 0; i < 900000; i++) {  
  11.                 d =  d + (Math.PI + Math.E) / d;  
  12.             }  
  13.             //給線程調度器可以切換到其它進程的信號  
  14.             Thread.yield();  
  15.         }  
  16.     }  
  17. }  
  18.   
  19. public class InterruptTaskTest {  
  20.       
  21.     public static void main(String[] args) throws Exception{  
  22.         //將任務交給一個線程執行  
  23.         Thread t = new Thread(new ATask());  
  24.         t.start();  
  25.           
  26.         //運行一斷時間中斷線程  
  27.         Thread.sleep(100);  
  28.         System.out.println("****************************");  
  29.         System.out.println("Interrupted Thread!");  
  30.         System.out.println("****************************");  
  31.         t.interrupt();  
  32.     }  
  33. }   


運行這個程序,我們發現調用interrupt()後,程序仍在運行,如果不強制結束,程序將一直運行下去,如下所示:
Java代碼  收藏代碼
  1. ......  
  2. I am running!  
  3. I am running!  
  4. I am running!  
  5. I am running!  
  6. ****************************  
  7. Interrupted Thread!  
  8. ****************************  
  9. I am running!  
  10. I am running!  
  11. I am running!  
  12. I am running!  
  13. I am running!  
  14. ....  

雖然中斷髮生了,但線程仍然在進行,離開線程有兩種常用的方法:
拋出InterruptedException和用Thread.interrupted()檢查是否發生中斷,下面分別看一下這兩種方法:
1.在阻塞操作時如Thread.sleep()時被中斷會拋出InterruptedException(注意,進行不能中斷的IO操作而阻塞和要獲得對象的鎖調用對象的synchronized方法而阻塞時不會拋出InterruptedException)
Java代碼  收藏代碼
  1. class ATask implements Runnable{  
  2.   
  3.     private double d = 0.0;  
  4.       
  5.     public void run() {  
  6.         //死循環執行打印"I am running!" 和做消耗時間的浮點計算  
  7.         try {  
  8.             while (true) {  
  9.                 System.out.println("I am running!");  
  10.                   
  11.                 for (int i = 0; i < 900000; i++) {  
  12.                     d =  d + (Math.PI + Math.E) / d;  
  13.                 }  
  14.                 //休眠一斷時間,中斷時會拋出InterruptedException  
  15.                 Thread.sleep(50);  
  16.             }  
  17.         } catch (InterruptedException e) {  
  18.             System.out.println("ATask.run() interrupted!");  
  19.         }  
  20.     }  
  21. }  

程序運行結果如下:
Java代碼  收藏代碼
  1. I am running!  
  2. I am running!  
  3. ****************************  
  4. Interrupted Thread!  
  5. ****************************  
  6. ATask.run() interrupted!  

可以看到中斷任務時讓任務拋出InterruptedException來離開任務.

2.Thread.interrupted()檢查是否發生中斷.Thread.interrupted()能告訴你線程是否發生中斷,並將清除中斷狀態標記,所以程序不會兩次通知你線程發生了中斷.
Java代碼  收藏代碼
  1. class ATask implements Runnable{  
  2.   
  3.     private double d = 0.0;  
  4.       
  5.     public void run() {  
  6.           
  7.         //檢查程序是否發生中斷  
  8.         while (!Thread.interrupted()) {  
  9.             System.out.println("I am running!");  
  10.   
  11.             for (int i = 0; i < 900000; i++) {  
  12.                 d = d + (Math.PI + Math.E) / d;  
  13.             }  
  14.         }  
  15.   
  16.         System.out.println("ATask.run() interrupted!");  
  17.     }  
  18. }  

程序運行結果如下:
Java代碼  收藏代碼
  1. I am running!  
  2. I am running!  
  3. I am running!  
  4. I am running!  
  5. I am running!  
  6. I am running!  
  7. I am running!  
  8. ****************************  
  9. Interrupted Thread!  
  10. ****************************  
  11. ATask.run() interrupted!  


我們可結合使用兩種方法來達到可以通過interrupt()中斷線程.請看下面例子:
Java代碼  收藏代碼
  1. class ATask implements Runnable{  
  2.   
  3.     private double d = 0.0;  
  4.       
  5.     public void run() {  
  6.           
  7.         try {  
  8.         //檢查程序是否發生中斷  
  9.         while (!Thread.interrupted()) {  
  10.             System.out.println("I am running!");  
  11.             //point1 before sleep  
  12.             Thread.sleep(20);  
  13.             //point2 after sleep  
  14.             System.out.println("Calculating");  
  15.             for (int i = 0; i < 900000; i++) {  
  16.                 d = d + (Math.PI + Math.E) / d;  
  17.             }  
  18.         }  
  19.           
  20.         } catch (InterruptedException e) {  
  21.             System.out.println("Exiting by Exception");  
  22.         }  
  23.           
  24.         System.out.println("ATask.run() interrupted!");  
  25.     }  
  26. }  

在point1之前處point2之後發生中斷會產生兩種不同的結果,可以通過修改InterruptTaskTest main()裏的Thread.sleep()的時間來達到在point1之前產生中斷或在point2之後產生中斷.
如果在point1之前發生中斷,程序會在調用Thread.sleep()時拋出InterruptedException從而結束線程.這和在Thread.sleep()時被中斷是一樣的效果.程序運行結果可能如下:
Java代碼  收藏代碼
  1. I am running!  
  2. Calculating  
  3. I am running!  
  4. Calculating  
  5. I am running!  
  6. Calculating  
  7. I am running!  
  8. ****************************  
  9. Interrupted Thread!  
  10. ****************************  
  11. Exiting by Exception  
  12. ATask.run() interrupted!  

如果在point2之後發生中斷,線程會繼續執行到下一次while判斷中斷狀態時.程序運行結果可能如下:
Java代碼  收藏代碼
  1. I am running!  
  2. Calculating  
  3. I am running!  
  4. Calculating  
  5. I am running!  
  6. Calculating  
  7. ****************************  
  8. Interrupted Thread!  
  9. ****************************  
  10. ATask.run() interrupted! 
發佈了1 篇原創文章 · 獲贊 6 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章