isInterrupted、interrupt和interrupted

由易到难开始介绍吧

isInterrupted

最容易理解的,查看线程是否被打断,没有副作用。可以自己询问自己,也可以在A线程中询问B线程。

       Thread A = new Thread(() -> {
            //自己询问自己
            Thread.currentThread().isInterrupted();
        },"A");
        A.start();
        Thread B = new Thread(() -> {
            //在B中询问A
            A.isInterrupted();
        },"B");
        B.start();

interrupt

最复杂的一个,分为几种情况:

  1. 如果线程此时正在InterruptibleChannel上执行I/O操作,线程的打断状态被设置为true,抛出异常
  2. 如果线程此时正被Selector阻塞,线程的打断状态被设置为true,线程立即返回一个非零值。
  3. 如果线程此时正被sleep、wait、join(包括这些函数带参数的版本)阻塞着呢,线程的打断状态被重置,即设为false,再抛出InterruptedException。这意味着如果在捕获InterruptedException的逻辑中不能通过isInterrupted或者interrupted来正确判断线程是否被打断,因为打断状态已经被重置了。
  4. 其他情况,打断状态被设置为true。
    注意 第一和第二都是与管道I/O相关的,平时都接触不到。当读取File时被打断不会抛出异常。

接下来演示第三和第四种情况

class Demo {

    static boolean flag = true;
    public static void main(String[] args) {
        ReentrantLock lock = new ReentrantLock();
        final Thread a = new Thread(() -> {
            synchronized (lock) {
                System.out.println(Thread.currentThread().getName() + "获得了锁");
                try {
                    flag = false;
                    lock.wait();
                } catch (InterruptedException e) {
                    //符合第三种情况,虽然a被b打断了,但这里返回的是false,即打断状态被重置了。
                    System.out.println("a捕获InterruptedException异常后Thread.currentThread().isInterrupted() " + Thread.currentThread().isInterrupted());
                    e.printStackTrace();
                }
            }
        }, "a");
        a.start();
        while (flag){}//保证a线程先于b线程执行
        new Thread(() -> {
            synchronized (lock) {
                //此时a线程还没有被打断,isInterrupted返回false,没有副作用
                System.out.println("b第一次询问a.isInterrupted() " + a.isInterrupted());
                //在b线程中打断a线程
                a.interrupt();
                //此时a线程被打断,isInterrupted返回true,没有副作用
                System.out.println("b第二次询问a.isInterrupted() " + a.isInterrupted());
                
                //没有阻塞的情况下打断线程,符合第四种情况,只是把打断状态设置为true
                Thread.currentThread().interrupt();
                System.out.println("b自我打断之后Thread.currentThread().interrupt() " + Thread.interrupted());
                lock.notify();
            }
        }, "b").start();
    }
}

结果如下图:
在这里插入图片描述
看一个读取文件的例子:

interrupted

最让人疑惑的一个。因为他又副作用。就是会重置线程的打断状态,即设置为false。可想而知,如果一个线程被interrupt了,再 马上连续多次 通过Thread.interrupted()查看,只有第一次是true,以后就是false。而isInterrupted不管调用几次都不会有副作用。
注意文中的 马上连续多次 ,要求多次Thread.interrupted()之间不能再被interrupt

Thread.currentThread().interrupt();
//连续多次调用Thread.interrupted()
System.out.println(Thread.interrupted());//true,打断状态被重置为false
System.out.println(Thread.interrupted());//false

Thread.currentThread().interrupt();
System.out.println(Thread.interrupted());//true
Thread.currentThread().interrupt();
System.out.println(Thread.interrupted());//true

总结

  1. 打断别人用a.interrupt();
  2. 打断自己用Thread.currentThread().interrupt();
  3. 查看别人的打断状态用a.isInterrupted();
  4. 查看自己的打断状态用Thread.currentThread().isInterrupted();

参考

作者:大闲人柴毛毛
链接:https://www.zhihu.com/question/41048032/answer/252905837
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值