3分钟了解interrupt

合理中断

Thread类中,提供了stop(),suspend()resume()方法,这三个方法分别是用来结束,暂停,恢复线程. 但是都已经被标记为@Deprecated废弃了. 因为一个线程不应该由其他线程来结束,他应该收到别人的通知,然后自己在合适的位置结束,如果不合理的结束,会导致很多意外的结果,比如临界区还没完全操作完,提前释放锁,但是部分状态已经改变,还有没有做一些清理操作等等.

基于上面的理由,Java提供了新的中断机制(interrupt),其他线程调用想要终止线程的interrupt()方法. 这个时候线程会根据自己的状态做出响应:

  • 如果线程处于阻塞状态(sleep,wait,join),则线程会抛出InterruptedException异常.
  • 如果线程处于正常运行状态,则还是正常运行,但是中断的标志被设置为true,相当于有人通知 你该结束自己了.

被调用线程处于阻塞状态

public static void main(String[] args) {
    Thread thread = new Thread() {
        @Override
        public void run() {
            try {
                // 被调线程阻塞自己30s
                sleep(30000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    };
    try {
        // 启动线程
        thread.start();
        // 主线程阻塞自己3秒
        TimeUnit.SECONDS.sleep(3);
        // 中断线程
        thread.interrupt();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
// ↓ 运行输出如下 ↓
// java.lang.InterruptedException: sleep interrupted
// ...

被调用线程处于正常运行

被调用线程不处于阻塞的时候,需要调用方法来监控标志.

public static void main(String[] args) {
    Thread thread = new Thread() {
        @Override
        public void run() {
            while (!Thread.interrupted()) {
                System.out.println("我还稳得住...");
            }
        }
    };
    try {
        thread.start();
        TimeUnit.SECONDS.sleep(3);
        thread.interrupt();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

// ↓ 运行输出如下 ↓
// 我能稳得住
// ...

该程序会在检测interrupt标志,如果发现interrupt标志设置为true,则会结束自己.

interrupted()和isInterrupt()的区别

区别: 是否会清除interrupt标志. isInterrupt()方法不会改变标志,而interrupted()方法会在检测的同时,如果发现标志为true,则会返回true,然后把标志置为false.

public static void main(String[] args) {
    Thread thread = new Thread() {
        @Override
        public void run() {
            while (!Thread.interrupted()) {
                System.out.println("我还稳得住...");
            }
            // ⚠️⚠️添加下面代码⚠️⚠️
            System.out.println(Thread.interrupted());
        }
    };
    try {
        thread.start();
        TimeUnit.SECONDS.sleep(3);
        thread.interrupt();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

// ↓ 运行输出如下 ↓
// 我还稳得住...
// ...(省略)
// false

上面实例说明Thread.interrupted()方法会在标志为true的情况下修改interrupted的标志.

public static void main(String[] args) {
    Thread thread = new Thread() {
        @Override
        public void run() {
            // ⚠️⚠️修改方法⚠️⚠️
            while (!isInterrupted()) {
                System.out.println("我还稳得住...");
            }
            System.out.println(Thread.interrupted());
        }
    };
    try {
        thread.start();
        TimeUnit.SECONDS.sleep(3);
        thread.interrupt();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

// ↓ 运行输出如下 ↓
// 我还稳得住...
// ...(省略)
// 我还稳得住
// true

源码解析

下图是Thread类的 interrupted 方法
interrupted方法
通过观察源码可以看出interrupted最后会调用isInterrupted(true),而传入的参数代表是否清除标志位.
isInterrupted方法
是否清楚标记是根据传入的参数为true还是false.

  1. true ⇒ 清除 interrupted state
  2. false ⇒ 不清除 interrupted state

可以看到isInterrupted(boolean)是一个本地方法,最终会通过C/C++来执行. 而isInterrupted()最后传入的参数为false,说明不清除标志位.

注意 interrupted 是静态方法. 可以使用Thread直接调用. 而isInterrupted 是成员方法,需要Thread对象. 可以通过 Thread.currentThread() 获取当前线程.

总结

  1. 理解如何打断线程, intterruptstop 的区别
  2. 理解 interrupt 打断的原理
  3. 熟悉操作清除 interrupted state
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值