java多线程-interrupt
2015-12-02 11:20
579 查看
java中的interrupt(中断)很容易让人产生歧义,仅从字面意思上理解是如果一个Thread实例调用了interrupt方法会中断该线程。而事实并不是这样,该方法知识为我们提供了一种中断的协作机制,真正什么时候去中断线程需要我们自己去定义中断的逻辑。因为interrupt方法仅仅是为该线程设置了中断标志,并不会中断线程,我们可以利用该中断标志来中断该线程。
我们一般采用两种方式中断当前线程:
一种是利用阻塞方法sleep(),wait(),join(),这几个方法会抛出InterruptException,当我们在调用了该线程的interrupt()方法时会抛出中断异常,然后我们就可以设置合理的逻辑使线程线程中断(我觉得用尽快跳出run方法,使任务提前结束来表述更为贴切)。注意一点就是一旦产生了中断异常后,线程的中断标志就会被自动清除(中断状态从true变为false)
另外一种就是在任务中不断检测线程的中断标志来实现线程的中断,java为我们提供了两个获取中断标志的方法一个是Thread.interrupted()的静态方法,另一个是isInterrupted()的实例方法,这两个方法会返回线程的中断状态。
通过代码来说明上面两种中断方法。
以上说明的是第一种中断子线程的方式,即在阻塞方法的异常处理中加入合适的逻辑中断线程
再来说明一下通过判断标志位状态的方式终止线程的方式
运行可以看到子线程会一致运行下去,因为主线程中调用子线程的interrupt()方法会使子线程的sleep方法产生一个中断异常,进而使该线程的中断标志清除(即中断标志变为false)。所以子线程会一直运行下去。
我们一般采用两种方式中断当前线程:
一种是利用阻塞方法sleep(),wait(),join(),这几个方法会抛出InterruptException,当我们在调用了该线程的interrupt()方法时会抛出中断异常,然后我们就可以设置合理的逻辑使线程线程中断(我觉得用尽快跳出run方法,使任务提前结束来表述更为贴切)。注意一点就是一旦产生了中断异常后,线程的中断标志就会被自动清除(中断状态从true变为false)
另外一种就是在任务中不断检测线程的中断标志来实现线程的中断,java为我们提供了两个获取中断标志的方法一个是Thread.interrupted()的静态方法,另一个是isInterrupted()的实例方法,这两个方法会返回线程的中断状态。
通过代码来说明上面两种中断方法。
<span style="font-size:14px;">package com.lql.thread3; /** * 通过阻塞方法抛出异常,当出现中断时阻塞方法产生一个中断异常 * 在异常处理中,采取合适的措施中断线程 * @author Administrator * */ public class MyInterrupt implements Runnable{ private boolean flag = true; @Override public void run() { // TODO Auto-generated method stub while(flag){ System.out.println("hello,world!"); try { Thread.sleep(100); } catch (InterruptedException e) { // TODO Auto-generated catch block //产生中断异常,在处理中断异常时可以选择终止本线程 System.out.println("在阻塞的时候,检测到中断,会产生InterruptedException"); //异常产生后,线程的中断标志会被标志位false //所以Thread.interrupted()会返回false System.out.println("Thread.interrupted() " + Thread.interrupted()); System.out.println("Thread.currentThread().isInterrupted() " +Thread.currentThread().isInterrupted()); //在这里修改标志,将本线程终止,标志位被修改后,当前线程就会跳出循环任务,之后线程就会被中断 flag = false; } } System.out.println(Thread.currentThread().getName() +"is stoped"); } }</span>
<span style="font-size:14px;">package com.lql.thread3; public class InterruptTest { public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(new MyInterrupt()); thread.start(); //主线程休眠100毫秒,让子线程可以执行一段时间 Thread.sleep(100); //在主线程中调用子线程的interrupt()方法,置子线程的中断标志为true //此时子线程的执行的sleep就会产生一个中断异常 thread.interrupt(); } }</span>运行结果
hello,world! hello,world! 在阻塞的时候,检测到中断,会产生InterruptedException Thread.interrupted() false Thread.currentThread().isInterrupted() false Thread-0is stoped
以上说明的是第一种中断子线程的方式,即在阻塞方法的异常处理中加入合适的逻辑中断线程
再来说明一下通过判断标志位状态的方式终止线程的方式
package com.lql.thread3; public class MyInterrupt2 implements Runnable{ @Override public void run() { // TODO Auto-generated method stub //通过不断检测线程的中断标志来判断是否中断当前线程的执行 while(!Thread.currentThread().isInterrupted()){ System.out.println("hello,world"); } System.out.println(Thread.currentThread().getName()+ " is stop"); } }
package com.lql.thread3; public class InterruptTest { public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(new MyInterrupt2()); thread.start(); //主线程休眠1毫秒,让子线程可以执行一段时间 Thread.sleep(1); thread.interrupt(); } }
hello,world hello,world hello,world hello,world hello,world Thread-0 is stop
</pre><p><span style="font-size:14px;">可以看到子线程运行一段时间后同样被中断中断了</span></p><p><span style="font-size:14px;"></span></p><p><span style="font-size:14px;">如果我们在子线程中加入一个阻塞方法比如sleep呢</span></p><p><span style="font-size:14px;"></span><pre name="code" class="java">package com.lql.thread3; public class MyInterrupt2 implements Runnable{ @Override public void run() { // TODO Auto-generated method stub //通过不断检测线程的中断标志来判断是否中断当前线程的 while(!Thread.currentThread().isInterrupted()){ System.out.println("hello,world"); try { Thread.sleep(50); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println(Thread.currentThread().getName()+ " is stop"); } }
运行可以看到子线程会一致运行下去,因为主线程中调用子线程的interrupt()方法会使子线程的sleep方法产生一个中断异常,进而使该线程的中断标志清除(即中断标志变为false)。所以子线程会一直运行下去。
相关文章推荐
- 字符串乱码处理,java
- 使用spring动态路由切换主从库
- spring transaction源码分析--事务架构
- JDK 和JRE的区别
- KMP算法(Knuth-Morris-Pratt ),java实现KMP算法
- Java多线程优先级的一些测试
- java传值还是传引用的问题详解
- 深入理解Java:内省(Introspector)
- Java 循环
- LeetCode 290 : Word Pattern (Java)
- Java语言基础之基本数据类型与数据类型转换
- eclipse配置NDK环境
- java 连接SQLserver
- Java集合练习:斗地主游戏
- LeetCode 20 : Valid Parentheses (Java)
- Maven学习总结(七)——eclipse中使用Maven创建Web项目
- Maven学习总结(六)——Maven与Eclipse整合
- QT跨平台--JAVA 命名规范
- Java if 判断
- [Java基础]浅析Java多态