Thread-打断一下,插个广告 ^ - ^

本文基于jdk1.8
在这里插入图片描述

一.那个Thread中断一下

如何停止一个运行线程呢?
很久以前通过stop(),这是属于抢占式的中断。强制停止一个线程,可能造成不可预估的后果。
举个例子:
例如正在玩游戏,耗时n久通过了,没存档,然后突然断电了。。。,这个后果是砸显示器还是砸显示器呢。
现在推荐调用interrupt(),这属于协作式中断。线程中断不代表线程的立即死亡,可能是中断返回等待新的任务,或是线程忙完任务选择合适的时机再死亡。
这意味着,调用interrupt,只是标识了线程中断状态,至于要不要死亡或者什么时候死亡这是线程自身决定的。

二.线程状态

在进入线程中断之前,先了解线程都有哪些状态:

  • NEW
    这个状态,表示线程还没启动,只是创建了一个线程
  • RUNNABLE
    jVM中处于可运行状态。
  • BLOCKED
    线程等待监视器锁的状态,例如IO堵塞住线程
  • WAITING
    等待线程的状态,等待另外线程执行特定操作。可以调用如下方法进入该状态:
  1. Object.wait没有超时
  2. Thread.join没有超时
  3. LockSupport.park
  • TIMED_WAITING
    线程超时等待状态,同 WAITING状态相似,只是多了限时操作。如下方法进入该状态:
    Thread.sleep
    Object.wait超时
    Thread.join超时
    LockSupport.parkNanos
    LockSupport.parkUntil
  • TERMINATED
    线程已完成执行的状态

这里有个注意点,不要搞混了BLOCKED和WAITING,翻译过来,感觉含义类似。

  • WAITING和TIMED_WAITING状态就是我们日常理解的“堵塞”,线程真的堵住了。
  • BLOCKED状态是指线程不占用cpu资源,但线程还在运行了,可能占用了网卡等其他资源

三. 来,断一下

在这里插入图片描述
不多说,直接测试下,哪些状态下,中断生效

1. NEW
  	public static void main(String[] args) {
        Thread thread = new Thread(() -> {
                System.out.println("中断了");
        });
        System.out.println("线程状态:"+thread.getState());
        System.out.println("线程中断状态前:"+thread.isInterrupted());
        thread.interrupt();
        System.out.println("线程中断状态后:"+thread.isInterrupted());
    }

运行结果如下,对于NEW状态,中断操作没有影响
在这里插入图片描述

2. RUNNABLE
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            Thread t1 = Thread.currentThread();
            System.out.println("线程状态:"+t1.getState());
            System.out.println("线程中断状态前:"+t1.isInterrupted());
            while (true) {
                if (Thread.currentThread().isInterrupted()) {
                    System.out.println("线程中断状态后:"+true);
                    break;
                }
            }
            System.out.println("断了断了");
        });
        thread.start();
        Thread.sleep(10L);
        System.out.println("开始中断");
        thread.interrupt();
    }

运行结果如下,对于RUNNABLE状态,中断操作会修改中断状态为true,但不影响线程继续运行。
在这里插入图片描述

3. BLOCKED
public class Solution {

    public static synchronized void addNum(boolean sleep) {
        if (!sleep) {
            return;
        }
        try {
            Thread.sleep(3000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            Solution.addNum(true);

        });
        Thread thread2 = new Thread(() -> {
            Solution.addNum(false);
            while (true) {
                if (Thread.currentThread().isInterrupted()) {
                    System.out.println("线程中断状态后:" + true);
                    break;
                }
            }
            System.out.println("断了断了");
        });
        thread.start();
        Thread.sleep(10L);
        thread2.start();
        System.out.println("线程中断状态前:" + thread2.isInterrupted());
        System.out.println("线程状态:" + thread2.getState());
        System.out.println("开始中断");
        thread2.interrupt();
    }


}

运行结果如下,对于BLOCKED状态,中断操作会修改中断状态为true,但不影响线程继续运行。
在这里插入图片描述

4. WAITING
   public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            System.out.println("线程中断状态前:" + Thread.currentThread().isInterrupted());
            LockSupport.park();
            System.out.println("断了断了");
        });
        thread.start();
        Thread.sleep(50L);
        System.out.println("线程状态:" + thread.getState());
        thread.interrupt();
        System.out.println("线程中断状态后:" + thread.isInterrupted());
    }

运行结果如下,对于WAITING状态,中断操作会修改中断状态为true,且影响线程运行。
这里调用LockSupport.park不抛出中断异常,其他例如wait()方法会抛异常的
在这里插入图片描述

5. TIMED_WAITING
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            System.out.println("线程中断状态前:" + Thread.currentThread().isInterrupted());
            try {
                Thread.sleep(3000L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("断了断了");
        });
        thread.start();
        Thread.sleep(50L);
        System.out.println("线程状态:" + thread.getState());
        thread.interrupt();
        System.out.println("线程中断状态后:" + thread.isInterrupted());
    }

运行结果如下,对于TIMED_WAITING状态,中断操作会修改中断状态为true,且影响线程运行。
在这里插入图片描述

6. TERMINATED
	public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
                System.out.println("中断了");
        });
        thread.start();
        Thread.sleep(2000L);
        System.out.println("线程状态:"+thread.getState());
        System.out.println("线程中断状态前:"+thread.isInterrupted());
        thread.interrupt();
        System.out.println("线程中断状态后:"+thread.isInterrupted());
    }

运行结果如下,对于TERMINATED状态,中断操作没有影响
在这里插入图片描述

7.堵塞已中断过的线程

    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            System.out.println("启动线程");
            LockSupport.park();
            System.out.println("恢复了继续走");
            System.out.println("看看状态怎么样:"+Thread.currentThread().isInterrupted());
            LockSupport.park();
            System.out.println("同样的招式对圣斗士无效的");
            // 重置状态,并返回之前的状态
            System.out.println("重置下,看下之前的状态:"+Thread.interrupted());
            System.out.println("看看当前状态2:"+Thread.currentThread().isInterrupted());
            LockSupport.park();
            System.out.println("断了断了");
        });
        thread.start();
        Thread.sleep(50L);
        System.out.println("开始中断线程" );
        thread.interrupt();
    }

运行结果如下,对已中断的线程,再次堵塞失效了,直到恢复默认中断状态才能生效。
在这里插入图片描述

四.总结

根据上面的测试结果,中断操作,总结如下:

  1. NEW ,TERMINATED对于这两种状态,中断操作没有一丝影响。
  2. RUNNABLE,BLOCKED 中断只会修改当前中断状态,但不影响线程运行。
  3. WAITINGTIMED_WAITING 中断会打断当前的堵塞状态,且修改当前中断状态。除了LockSupport.park外的操作会抛出中断异常。
  4. 对已中断的线程,堵塞操作无效,除非恢复默认中断状态。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值