前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >线程应用 - 中断interrupt详解

线程应用 - 中断interrupt详解

作者头像
虞大大
发布于 2020-08-26 09:18:12
发布于 2020-08-26 09:18:12
1.2K00
代码可运行
举报
文章被收录于专栏:码云大作战码云大作战
运行总次数:0
代码可运行

有些初学者对中断的概念可能会有些许小误会,比如线程调用Thread.interrupt()方法,就认为线程会被中断,停止执行,其实不是这样的,让我们来看下中断interrupt详解。

一、interrupt方法

源码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public void interrupt() {    //判断是否操作线程
    if (this != Thread.currentThread())
checkAccess();    synchronized (blockerLock) {
        Interruptible b = blocker;
        if (b != null) {            //只是设置中断标记位
interrupt0();           // Just to set the interrupt flag
            b.interrupt(this);
            return;
        }
    }
    interrupt0();
}

可以看到interrupt方法并不会对任务终止线程的操作,仅仅只是设置了一个中断的标记位。为了不造成误解,我们看以下示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class InterruptTest {
    public static void main(String[] args) {
        new test().start();
    }
}
class test extends Thread {
    static int n = 10;
    public void run() {
        for (int i = 0; i < 15; i++) {
            if (i == n) {
                System.out.println("线程要被中断了:" + i);
                this.interrupt();
            }
            System.out.println("当前运行数字为:" + i);
        }
    }
}

如果interrupt方法会直接终止线程的话,那么当上述代码中的i为10时,后面就不会再继续执行下去了,运行结果为:

可以看到线程还是运行到了最后。正如源码中所说的那样,调用interrupt仅仅只是做了一个中断标识而已,其余并不会做任何操作。

但是也不能说interrupt方法是完全没有任何作用的,因为interrupt方法对于java来说其实是一个协作机制,调用interrupt方法会把调用线程的中断状态设置为true,而其他需要依赖这个中断符的方法在运行时如果监测到这个中断标志就会作出响应。

下面示例,使用Thread.sleep方法观察运行结果。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class InterruptTest {
    public static void main(String[] args) {
        new test().start();
    }
}
class test extends Thread {
    static int n = 10;
    public void run() {
        for (int i = 0; i < 15; i++) {
            if (i == n) {
                System.out.println("线程要被中断了:" + i);
                this.interrupt();
                System.out.println("线程调用中断方法:" + i);
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
                break;
            }
            System.out.println("当前运行数字为:" + i);
        }
    }
}

运行结果:

上述运行过程中每一次循环都会调用Thread.sleep方法,将线程休眠1秒钟,然而当第10次循环,调用interrupt方法后再调用休眠方法则抛出了异常。

这样的情况在Object.wait等方法中也会出现。所以interrupt相当于java的一个协作机制,如果调用了Object.wait或Thread.sleep方法,会判断线程的中断标志位,如果发现他被设置为true后(线程可以调用interrupt方法来修改标志位),则会抛出异常,后续如果线程不想继续被操作,可以利用这个异常来让线程运行退出,比如for循环的break,或者直接return。

二、isInterrupted方法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public boolean isInterrupted() {
    return isInterrupted(false);
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private native boolean isInterrupted(boolean ClearInterrupted);

检测线程是否中断方法,如果当前线程已经中断则返回true,否则返回false。继续使用上述例子,观察结果:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class InterruptTest {
    public static void main(String[] args) {
        new test().start();
    }
}
class test extends Thread {
    static int n = 10;
    public void run() {
        for (int i = 0; i < 15; i++) {
            if (i == n) {
                System.out.println("线程要被中断了:" + i);
                this.interrupt();
                System.out.println("线程调用中断方法:" + i);
                boolean flag = this.isInterrupted();
                System.out.println("线程是否被中断:" + flag);
            }
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
                break;
            }
            System.out.println("当前运行数字为:" + i);
        }
    }
}

运行结果:

结果发现,线程是否被中断检测方法返回了true。

三、interrupted方法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static boolean interrupted() {
    return currentThread().isInterrupted(true);
}

interrupted方法是线程类中的静态方法,在api文档中的说明为返回并清除中断状态。

使用上述例子并将isInterrupted方法替换为interrupted方法。观察结果:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class InterruptTest {
    public static void main(String[] args) {
        new test().start();
    }
}
class test extends Thread {
    static int n = 10;
    public void run() {
        for (int i = 0; i < 15; i++) {
            if (i == n) {
                System.out.println("线程要被中断了:" + i);
                this.interrupt();
                System.out.println("线程调用中断方法:" + i);
                boolean flag = Thread.interrupted();
                System.out.println("线程是否被中断:" + flag);
            }
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
                break;
            }
            System.out.println("当前运行数字为:" + i);
        }
    }
}

运行结果:

上述结果发现,线程在调用Thread.sleep后并没有被中断。加入isInterrupted方法观察线程中断标志位情况:

运行结果说明调用中断方法后调用Thread.sleep方法,没有中断的原因是因为调用了interrupted方法,将中断标志位重置为了false。而interrupted方法返回了true是因为,在重置之前,他的中断标志位是正常的。

四、总结

上述测试和分析了以后对这三个方法应该就比较清晰了。

(1)interrupt方法其实是修改中断标记位为true,起到一个协助的作用,但是并不会真正的终止线程。

(2)isInterrupted方法最纯粹,就是判断当前线程是否有中断标记位,返回结果为true或false。

(3)interrupted方法是一个静态方法,返回的是调用方法前的中断标记位,并清除中断标记位为false。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-06-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码云大作战 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档