java多线程-interrupt

来源:互联网 发布:ubuntu改ip 编辑:程序博客网 时间:2024/06/05 00:56

java中的interrupt(中断)很容易让人产生歧义,仅从字面意思上理解是如果一个Thread实例调用了interrupt方法会中断该线程。而事实并不是这样,该方法知识为我们提供了一种中断的协作机制,真正什么时候去中断线程需要我们自己去定义中断的逻辑。因为interrupt方法仅仅是为该线程设置了中断标志,并不会中断线程,我们可以利用该中断标志来中断该线程。

我们一般采用两种方式中断当前线程:

一种是利用阻塞方法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;@Overridepublic void run() {// TODO Auto-generated method stubwhile(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()会返回falseSystem.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!在阻塞的时候,检测到中断,会产生InterruptedExceptionThread.interrupted() falseThread.currentThread().isInterrupted() falseThread-0is stoped

以上说明的是第一种中断子线程的方式,即在阻塞方法的异常处理中加入合适的逻辑中断线程


再来说明一下通过判断标志位状态的方式终止线程的方式

package com.lql.thread3;public class MyInterrupt2 implements Runnable{@Overridepublic 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,worldhello,worldhello,worldhello,worldhello,worldThread-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{@Overridepublic 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 blocke.printStackTrace();}}System.out.println(Thread.currentThread().getName()+ " is stop");}}

运行可以看到子线程会一致运行下去,因为主线程中调用子线程的interrupt()方法会使子线程的sleep方法产生一个中断异常,进而使该线程的中断标志清除(即中断标志变为false)。所以子线程会一直运行下去。


0 0