Thread--interrupt和线程终止

interrupt()的作用是中断本线程,本线程中断自己是被允许的,其他线程调用本线程的interrupt()方法时,会通过checkAccess()检查权限,可能会抛出SecurityException异常。

一、终止处于“阻塞状态”的线程:
通过中断方式终止处于阻塞状态的线程,当线程由于被调用了sleep(),wait(),join()等方法而进入阻塞状态,此时调用线程的interrupt()将线程的中断标记为true。由于处于阻塞状态,中断标记会被清除,同时产生一个InterruptedException异常,将InterruptedException放在适当的位置就能终止线程,形式如下:
[java]  view plain  copy
  1. @Override  
  2. public void run()   
  3. {  
  4.     try {  
  5.     while (true) {  
  6.         // 执行任务...  
  7.     }  
  8.     } catch (InterruptedException ie) {  
  9.         // 由于产生InterruptedException异常,退出while(true)循环,线程终止!  
  10.     }  
  11. }  
说明:在while(true)中不断的执行任务,当线程处于阻塞状态时,调用线程的interrupt()方法会产生InterruptedException中断,中断的捕获在while(true)之外,这样就退出了while(true)循环。
对InterruptException的捕获一定要放在while(true)循环体的外面,这样产生异常时就退出了while(true)循环,否则,InterruptException在while(true)循环体之外,就需要额外的添加退出处理,形式如下:
[java]  view plain  copy
  1. @Override  
  2. public void run() {  
  3.     while (true) {  
  4.         try {  
  5.             // 执行任务...  
  6.         } catch (InterruptedException ie) {  
  7.         // InterruptedException在while(true)循环体内。  
  8.         // 当线程产生了InterruptedException异常时,while(true)仍能继续运行!需要手动退出  
  9.         break;  
  10.         }  
  11.      }  
  12. }  
上面的InterruptedException异常的捕获是在while(true)中,当产生异常被catch时,仍然在while(true)循环体内,要退出while(true)循环体,需要额外的执行 操作。

二、终止处于运行状态的线程
通过标记方式终止处于运行状态的线程,其中,包括“中断标记”和“额外添加标记”
(1)通过“中断标记”终止线程,形式如下:
[java]  view plain  copy
  1. @Override  
  2. public void run() {  
  3.     while (!isInterrupted()) {  
  4.     // 执行任务...  
  5.     }  
  6. }  
说明:isInterrupted()是判断线程的中断标记是不是为true,当前线程处于运行状态,并且我们需要终止它时,可以调用线程的interrupt()方法,使用线程的中断标记为true,即isInterrupted()会返回true,此时,就会退出while循环。 interrupt()并不会终止处于“运行状态”的线程,它会将线程的中断标记设为true

(2)通过“额外添加标记”,形式如下:
[java]  view plain  copy
  1. rivate volatile boolean flag= true;  
  2.     protected void stopTask() {  
  3.         flag = false;  
  4.     }  
  5.   
  6. @Override  
  7. public void run() {  
  8.     while (flag) {  
  9.     // 执行任务...  
  10.     }  
  11. }  
说明:线程中有一个flag标记,它的默认值是true,并且我们提供stopTask()来设置flag标记,当我们需要终止该线程时,调用该线程的stopTask()方法就可以让线程退出while循环。 其中将flag定义为volatile类型,保证flag的可见性,其他线程通过stopTask()修改了flag之后,本线程能看到修改后的flag的值。
综合终止处于“阻塞状态”和“运行状态”的终止方式。
[java]  view plain  copy
  1. @Override  
  2. public void run() {  
  3.     try {  
  4.         // 1. isInterrupted()保证,只要中断标记为true就终止线程。  
  5.         while (!isInterrupted()) {  
  6.         // 执行任务...  
  7.         }  
  8.      } catch (InterruptedException ie) {  
  9.         // 2. InterruptedException异常保证,当InterruptedException异常产生时,线程被终止。  
  10.      }  
  11. }  
三、终止线程的示例
interrupt()常常被用来终止“阻塞状态”线程,参考示例:
[java]  view plain  copy
  1. class MyThread extends Thread {  
  2.   
  3.     public MyThread(String name) {  
  4.         super(name);  
  5.     }  
  6.   
  7.     @Override  
  8.     public void run() {  
  9.       try {  
  10.             int i=0;  
  11.             while (!isInterrupted())  
  12.             {  
  13.                 System.out.println("thread is running");  
  14.                 Thread.sleep(100); // 休眠100ms  
  15.                 i++;  
  16.                 System.out.println(Thread.currentThread().getName()+" ("+this.getState()+") loop " + i);  
  17.             }  
  18.         } catch (InterruptedException e) {  
  19.             System.out.println(Thread.currentThread().getName() +" ("+this.getState()+") catch InterruptedException.");  
  20.         }  
  21.     }  
  22. }  
  23.   
  24. public class Hello {  
  25.   
  26.     public static void main(String[] args) {  
  27.         try {  
  28.             Thread t1 = new MyThread("t1");  // 新建“线程t1”  
  29.             System.out.println(t1.getName() +" ("+t1.getState()+") is new.");  
  30.   
  31.             t1.start();                      // 启动“线程t1”  
  32.             System.out.println(t1.getName() +" ("+t1.getState()+") is started.");  
  33.             // 主线程休眠300ms,然后主线程给t1发“中断”指令。  
  34.             System.out.println("MainThread sleep");  
  35.             Thread.sleep(300);  
  36.             System.out.println("Thread interrupt");  
  37.             t1.interrupt();  
  38.             System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted.");  
  39.   
  40.             // 主线程休眠300ms,然后查看t1的状态。  
  41.             System.out.println("MainThread sleep");  
  42.             Thread.sleep(300);  
  43.             System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted now.");  
  44.         } catch (InterruptedException e) {  
  45.             e.printStackTrace();  
  46.         }  
  47.     }  
  48. }  
运行结果:
t1 (NEW) is new.
t1 (RUNNABLE) is started.
MainThread sleep
thread is running
t1 (RUNNABLE) loop 1
thread is running
t1 (RUNNABLE) loop 2
thread is running
t1 (RUNNABLE) loop 3
thread is running
Thread interrupt
t1 (TIMED_WAITING) is interrupted.
MainThread sleep
t1 (RUNNABLE) catch InterruptedException.
t1 (TERMINATED) is interrupted now.
结果说明:
(1)主线程main中会通过new MyThread("t1")创建线程t1,之后通过t1.start()启动线程t1
(2)t1启动之后,会不断的检查他的中断标记,如果中断标记为false,则休眠100ms
(3)t1休眠之后会切换到主线程main,主线程再次运行时,会执行t1.interrupt()中断线程t1。t1收到中断指令之后,会将t1的中断标志设置为false,而且会抛出InterruptedException异常,在t1的run()方法中,是在循环体之外捕获的异常,因此循环被终止。

通过“额外添加标记”的方式终止“运行状态”的线程的示例:
[java]  view plain  copy
  1. class MyThread extends Thread {  
  2.   
  3.     private volatile boolean flag= true;  
  4.     public void stopTask() {  
  5.         flag = false;  
  6.     }  
  7.   
  8.     public MyThread(String name) {  
  9.         super(name);  
  10.     }  
  11.   
  12.     @Override  
  13.     public void run() {  
  14.         synchronized(this) {  
  15.             try {  
  16.                 int i=0;  
  17.                 while (flag) {  
  18.                     Thread.sleep(100); // 休眠100ms  
  19.                     i++;  
  20.                     System.out.println(Thread.currentThread().getName()+" ("+this.getState()+") loop " + i);  
  21.                 }  
  22.             } catch (InterruptedException ie) {  
  23.                 System.out.println(Thread.currentThread().getName() +" ("+this.getState()+") catch InterruptedException.");  
  24.             }  
  25.         }  
  26.     }  
  27. }  
  28. public class Hello {  
  29.   
  30.     public static void main(String[] args) {  
  31.         try {  
  32.             MyThread t1 = new MyThread("t1");  // 新建“线程t1”  
  33.             System.out.println(t1.getName() +" ("+t1.getState()+") is new.");  
  34.   
  35.             t1.start();                      // 启动“线程t1”  
  36.             System.out.println(t1.getName() +" ("+t1.getState()+") is started.");  
  37.   
  38.             // 主线程休眠300ms,然后主线程给t1发“中断”指令。  
  39.             Thread.sleep(300);  
  40.             System.out.println("stopTask");  
  41.             t1.stopTask();  
  42.             System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted.");  
  43.   
  44.             // 主线程休眠300ms,然后查看t1的状态。  
  45.             Thread.sleep(300);  
  46.             System.out.println(t1.getName() +" ("+t1.getState()+") is interrupted now.");  
  47.             } catch (InterruptedException e) {  
  48.             e.printStackTrace();  
  49.             }  
  50.     }  
  51. }  
interrupt()和isInterrupted()都能够用于检测对象的“中断标记”,区别是interruptrf()除了返回中断标记外,它还会清除中断标记(即将中断标记设为false),而isInterrupted()仅仅返回中断标记。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值