java线程中断的艺术

引言

我们通过并发编程提升了系统的吞吐量,特定场景下我们希望并发的线程能够及时的合理的停止,所以就来聊聊java并发编程中中断的哲学。

java中的中断

何时触发中断阻塞

当出现以下几种情况,线程就会触发阻塞或者暂停:

  1. 等待IO操作返回
  2. 等待线程休眠醒来
  3. 等待获取java同步锁

此时,线程就会处于BLOCKEDWAITINGTIMED_WAITING、几种状态

如何响应中断

在操作系统中,线程的中断方式一般有两种:

  1. 抢占式:当线程需要中断时,直接让线程立刻停止手里的任务。
  2. 协作式:当线程需要中断时,通过标识告知线程需要被中断,线程轮询时看到这个标识就会直接中断。

而Java线程则是采用协作式中断,通知对于中断的后线程触发InterruptedException,通常来说我们对线程中断响应度越高,就越容易及时取消一些非必要的操作,对应按照如下两种方式进行响应:

如果当前业务层面不具备处理此类异常的能力,那么就将异常向上层抛出传递给调用者:

public void func() throws InterruptedException {
   
        Thread.interrupted();
    }

如果类似于Runnable 这种无法向上抛出的内置接口类的实现,我们则可以主动去捕获中断,并将当前线程打断从而让高层栈帧感知到这个异常中断:

class Task implements Runnable {
   

        @Override
        public void run() {
   
            try {
   
                Thread.sleep(1000);
            } catch (InterruptedException e) {
   
                //打断当前线程引发更高层线程响应此中断
                Thread.currentThread().interrupt();
            }
        }
    }

中断的一些实践

基于标识取消任务

所以对于线程的的中断,我们可以采用协作式标识来停止线程,通过任务运行时轮询检测,一旦看到标识设置为true即已请求取消,则提前结束运行。

就像下面这段代码,我希望的任务是每个1s输出一次,为了让任务的能够及时停止,我们采用volatile标识cancelled,这样就能取消操作尽可能及时可见:

public class Task implements Runnable {
   
    /**
     * 使用volatile修饰保证标识修改可见
     */
    private volatile boolean cancelled = false;

    private final Thread thread = new Thread(this);

    public void start() {
   
        thread.start();
    }

    /**
     * 停止时,通过cancel请求取消
     */
    public void cancel() {
   
        cancelled = true;

    }

   
    @Override
    public void run() {
   
        //取消标识检测,如果取消则直接结束循环
        while (!cancelled) {
   
            System.out.println("running");
            ThreadUtil.sleep(1000)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

shark-chili

您的鼓励将是我创作的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值