用interrupt()中断Java线程

时间:2021-07-22 18:38:43

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

最近在学习Java线程相关的东西,和大家分享一下,有错误之处欢迎大家指正.

假如我们有一个任务如下,交给一个Java线程来执行,如何才能保证调用interrupt()来中断它呢?

Java代码 用interrupt()中断Java线程 用interrupt()中断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. public class InterruptTaskTest { 
  19.      
  20.     public staticvoid main(String[] args) throws Exception{ 
  21.         //将任务交给一个线程执行 
  22.         Thread t = new Thread(new ATask()); 
  23.         t.start(); 
  24.          
  25.         //运行一断时间中断线程 
  26.         Thread.sleep(100); 
  27.         System.out.println("****************************"); 
  28.         System.out.println("Interrupted Thread!"); 
  29.         System.out.println("****************************"); 
  30.         t.interrupt(); 
  31.     } 
  32. }  



运行这个程序,我们发现调用interrupt()后,程序仍在运行,如果不强制结束,程序将一直运行下去,如下所示:

Java代码 用interrupt()中断Java线程 用interrupt()中断Java线程用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代码 用interrupt()中断Java线程 用interrupt()中断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.         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.     } 


程序运行结果如下:

Java代码 用interrupt()中断Java线程 用interrupt()中断Java线程用interrupt()中断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代码 用interrupt()中断Java线程 用interrupt()中断Java线程用interrupt()中断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.     } 


程序运行结果如下:

Java代码 用interrupt()中断Java线程 用interrupt()中断Java线程用interrupt()中断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代码 用interrupt()中断Java线程 用interrupt()中断Java线程用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.     } 


在point1之前处point2之后发生中断会产生两种不同的结果,可以通过修改InterruptTaskTest main()里的Thread.sleep()的时间来达到在point1之前产生中断或在point2之后产生中断.
如果在point1之前发生中断,程序会在调用Thread.sleep()时抛出InterruptedException从而结束线程.这和在Thread.sleep()时被中断是一样的效果.程序运行结果可能如下:

Java代码 用interrupt()中断Java线程 用interrupt()中断Java线程用interrupt()中断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代码 用interrupt()中断Java线程 用interrupt()中断Java线程用interrupt()中断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!