Java多线程——如何中断线程

来源:互联网 发布:原油eia库存数据公布 编辑:程序博客网 时间:2024/05/16 11:01

在讲解中断线程之前,需要了解一下三个函数的具体作用

1. interrupt(): interrupt的字面意思就是中断的意思,所以对不太了解Java多线程编程的同学来说,很容易误解直接调用该函数实现线程中断,其实这个函数的真正含义并非如此,它并不能马上停止线程的执行。线程调用此方法仅仅是将该线程的中断标志位设为true(默认为false),所以总的来说该函数的主要作用就是产生中断信号,设置中断标志。当程序检测到该线程的中断标志为true,采取何种操作,不管是中断还是继续运行,都有编码的人自己实现。

2. interrupted():检测当前线程是否为中断状态,该方法具有清除中断标志位为false的功能,即执行完该方法,线程的中断标志位会被置为false。查看该方法的 定义public static boolean interrupted()可知该方法为一个静态方法。

3. isInterrupted(): 此方法与interrupted的大体功能类似,可以测试线程Thread对象是否是中断状态,但有一点不同就是该方法不能清除中断状态标志。该方法的声明如下public boolean isInterrupted(),可以看到此方法不是一个静态方法。

了解了上述三个函数的作用,可以用如下的方法来完成线程的中断了。在线程执行或者处于阻塞状态时,检测中断标志位,如果标志位为true,抛出异常执行中断操作。在实现过程中对于处于执行状态和阻塞状态的线程其实是不同的,对于处于执行状态的线程,在检测到中断标志为true时,需要手动抛出InterruptedException,而处于阻塞状态的sleep(),wait()和join()则不需要,当检测到中断标志为true,会自动抛出InterruptedException。下面的两个例子分别展示了这两种情况。

执行状态的线程中断:

public class MyThread extends Thread{@Overridepublic void run() {try{for(int i=0; i<50000; i++){if(Thread.interrupted()){throw new InterruptedException(); //如果中断标志为true,抛出异常}System.out.println("i=" + (i+1));}} catch (InterruptedException e) {System.out.println("线程已被中断!");System.out.println("the signal of interrupted: "+Thread.interrupted()); //interrupted()方法的清除中断标志位功能检测e.printStackTrace();}}}
<pre name="code" class="java">public class Run {public static void main(String args[]){try{MyThread thread = new MyThread();thread.start(); //启动线程Thread.sleep(100);thread.interrupt(); //产生中断信号} catch (InterruptedException e) {System.out.println("main catch");e.printStackTrace();}}}


上述代码的执行结果为:

可以看到正在执行自增操作的线程被中断,还可以观察到interrupted()方法会清除中断标志为false。

处于sleep()状态的线程中断:

public class MyThread extends Thread{@Overridepublic void run() {try{System.out.println("run begin");Thread.sleep(20000);System.out.println("run end");} catch (InterruptedException e) {System.out.println("线程已被中断!");System.out.println("the signal of interrupted: "+Thread.interrupted());e.printStackTrace();}}}
public class Run {public static void main(String args[]){try{MyThread thread = new MyThread();thread.start();Thread.sleep(100);thread.interrupt();} catch (InterruptedException e) {System.out.println("main catch");e.printStackTrace();}}}
上述代码的执行结果如下图所示:


可以看到在阻塞状态(sleep,wait,join)的线程的中断实现,并不需要手动抛出异常,线程会自动抛出异常。并且在抛出异常的同时,还会将中断标志位置为false。但并不是所有的阻塞状态都可以自动抛出InterruptedException,像某些I/O操作或者内部锁操作,但是这些阻塞状态又会抛出自己特殊的异常,用这些异常同样可以实现中断。


0 0
原创粉丝点击