【Java】【多线程】线程interrupt

6 篇文章 0 订阅


学而不思则罔,思而不学则殆


初步了解

interrupt简单熟悉。

    private static void testInterrupt() throws InterruptedException {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println("Sleep ... ");
                    TimeUnit.MINUTES.sleep(1);
                } catch (InterruptedException e) {
                    //e.printStackTrace();
                    System.out.println("Oh, I am be interrupted.");
                }
            }
        });

        thread.start();
        TimeUnit.SECONDS.sleep(2);
        thread.interrupt();
    }

创建一个线程,休眠1分钟,但是在另一个线程执行了interrupt打断了该线程的休眠,线程不会休眠1分钟,会在2秒后被中断。

Sleep ... 
Oh, I am be interrupted.

interrupt这个方法到底做了什么呢?在一个线程内部存着一个命名为interrupt flag的标识,如果一个线程被interrupt,那么他的flag将被设置。
中断相关的方法有三个:

方法属性说明是否修改标识
interrupt类方法设置中断标识修改标识(设置标识)
isInterrupted类方法判断线程是否中断不修改标识
interrupted静态方法判断线程是否中断修改标识(擦除标识)

isInterrupted

isInterrupted是Thread的一个成员方法,它主要判断当前线程是否被中断,而且该方法仅是对interrupt标识的一个判断,并不会影响标识发生任何改变。

isInterrupted 测试一

线程中是空实现,调用interrupt打断线程,然后打印中断标识

    private static void testInterrupt() throws InterruptedException {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){
                   //空实现
                }
            }
        });

        thread.setDaemon(true);//设置守护线程,没有非守护线程会退出
        thread.start();
        TimeUnit.SECONDS.sleep(1);
        System.out.println("thread 1 = " + thread.isInterrupted());
        thread.interrupt();//打断
        System.out.println("thread 2 = " + thread.isInterrupted());
        TimeUnit.SECONDS.sleep(1);
        System.out.println("thread 3 = " + thread.isInterrupted());
    }

测试一结果

thread 1 = false
thread 2 = true
thread 3 = true

最开始标识是false,在执行interrupt后,标识是true。说明线程被打断,只是没有处理。

isInterrupted 测试二

线程中是有sleep,可捕获到中断方法,调用interrupt打断线程,然后打印中断标识

    private static void testInterrupt() throws InterruptedException {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println("Sleep ... ");
                    TimeUnit.MINUTES.sleep(1);
                } catch (InterruptedException e) {
                    //e.printStackTrace();
                    System.out.println("Oh, I am be interrupted.");
                }
            }
        });

        thread.setDaemon(true);
        thread.start();
        TimeUnit.SECONDS.sleep(1);
        System.out.println("thread 1 = " + thread.isInterrupted());
        thread.interrupt();
        System.out.println("thread 2 = " + thread.isInterrupted());
        TimeUnit.SECONDS.sleep(1);
        System.out.println("thread 3 = " + thread.isInterrupted());
    }

测试二结果

Sleep ... 
thread 1 = false
Oh, I am be interrupted.
thread 2 = false
thread 3 = false

执行中断interrupt。为啥拿到的中断标识还是false?因为sleep方法是一个可中断方法,会捕获中断标识并擦出,所以获取的中断标识是false。

对比两个测试的结果,可以得出一些结论:

  1. isInterrupted可以获取当前线程的中断标识,不会改变标识
  2. sleep方法会捕获中断标识,捕获到后会把标识改为false

interrupted

interrupted是一个静态方法,虽然其也用于判断当前线程是否被中断,但是它和成员方法isInterrupted不同,调用该方法会直接擦除interrupt标识。

interrupted测试

测试当线程的是否被中断。

    private static void testInterrupted() throws InterruptedException {
        Thread.currentThread().interrupt();
        System.out.println(Thread.currentThread().isInterrupted());
        System.out.println(Thread.interrupted());
        System.out.println(Thread.interrupted());
    }

测试一结果

true
true
false

调用interrupt后,设置标识为true。第一次调用interrupted返回的true,并擦除,所以第二次调用interrupted返回的false。isInterrupted不会改变标识,所以为true。

源码解析

//Tests if some Thread has been interrupted. The interrupted state is reset or not based on the value of ClearInterrupted that is passed.
private native boolean isInterrupted(boolean ClearInterrupted);

true 清除标识 false 不清除

    public boolean isInterrupted() {
        return isInterrupted(false);
    }
    public static boolean interrupted() {
        return currentThread().isInterrupted(true);
    }
  1. isInterrupted和interrupted调用的都是同一个native方法,
  2. isInterrupted方法中的ClearInterrupted = false,表示不想擦除
  3. interrupted方法中的ClearInterrupted = true,表示想擦除

那么当一个线程没有执行可中断方法之前就被打断,那么接下来该如何执行呢?

    private static void testInterrupt1() {
        Thread thread = Thread.currentThread();
        //1.判断当前线程是否中断
        System.out.println("currentThread is interrupt 0 ? " + Thread.interrupted() + " time:" + System.currentTimeMillis());
        thread.interrupt(); //2.执行打断方法
        System.out.println("currentThread is interrupt 1 ? " + thread.isInterrupted() + " time:" + System.currentTimeMillis());
        try {
            //3.执行可中断方法sleep
            TimeUnit.MINUTES.sleep(1);//会擦出interrupt标识
        } catch (InterruptedException e) {
            //e.printStackTrace();
            //4.捕获中断信号
            System.out.println("Oh, I am be interrupted.");
        }
        //5.打印中断标识
        System.out.println("currentThread is interrupt 2 ? " + thread.isInterrupted() + " time:" + System.currentTimeMillis());
    }

结果:

currentThread is interrupt 0 ? false time:1599277740140
currentThread is interrupt 1 ? true time:1599277740140
Oh, I am be interrupted.
currentThread is interrupt 2 ? false time:1599277740141

可见sleep立马就结束,立马被打断,标识为false。

总结

interrupt只是添加打断标识,真正打断逻辑还需要我们自己来实现。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值