Interrupt中断线程注意点

时间:2021-03-22 18:38:11

首先我们要明确,线程中断并不会使线程立即退出,而是发送一个通知,告知目标线程你该退出了,但是后面如何处理,则完全有目标线程自行决定。

这就是和stop()不一样的地方,stop执行后线程会立即终止,这样可能会引起数据不一致的问题(所以stop()方法已经被废弃不推荐使用了)。

线程中断有三个方法

public void Thread.interrupt();    //中断线程,设置中断标志位
public void Thread.isInterrupted();    //判断是否被中断
public void Thread.interrupted();    //判断是否被中断,并清除当前中断状态

先看下面一段代码

public class InterruptThread {

    public static void main(String[] args) throws Exception {
        Thread thread = new Thread() {
            public void run() {
                while (true) {
                    Thread.yield();
                }
            }
        };
        thread.start();
        Thread.sleep(2000);
        thread.interrupt();// 设置中断标志位
    }
}

 

虽然对thread进行了中断,但是thread并没有中断处理逻辑,所以这个中断就不起作用,否则,中断就和stop没什么两样了。

再看下面的代码

package com.thread.test;

public class InterruptThread {

    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread() {
            public void run() {
                while (true) {
                    //Thread.currentThread().isInterrupted();检查中断标志位--检查线程是否有被中断
                    if (Thread.currentThread().isInterrupted()) {
                        System.out.println("被中断了");
                        break;
                    }
                    Thread.yield();
                }
            };
        };
        thread.start();
        Thread.sleep(2000);
        thread.interrupt();//设置中断标志位
    }

}
isInterrupted()用于判断线程是否被中断,如果被中断则退出循环体。
请注意,代码中sleep()方法总会抛出一个
InterruptedException中断异常,它不是运行时异常,因此我们必须捕获它并处理,当线程在睡眠的时候如果被中断,这个异常就会产生
请看以下代码
package com.thread.test;

public class InterruptThread {

    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread() {
            public void run() {
                while (true) {
                    System.out.println("未被中断");
                    //Thread.currentThread().isInterrupted();检查中断标志位--检查线程是否有被中断
                    if (Thread.currentThread().isInterrupted()) {
                        System.out.println("被中断了");
                        break;
                    }
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        System.err.println("睡眠时发生了中断异常");
                        Thread.currentThread().interrupt();//设置中断标志位
                    }
                    Thread.yield();
                }
            };
        };
        thread.start();
        Thread.sleep(2000);
        thread.interrupt();//设置中断标志位
    }

}

运行后输出结果为:

未被中断
睡眠时发生了中断异常
未被中断
被中断了

注意:sleep()方法由于中断而抛出异常,此时,它会清除中断标记,如果不加以处理,那么下一次循环开始时,就无法捕获这个中断,故在异常处理中,再次设置中断标记位

如果不再次设置,则会输出如下结果:

未被中断
睡眠时发生了中断异常
未被中断
未被中断
未被中断
未被中断
.......
...
.