Java并发编程实战————恢复中断

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u014745069/article/details/87889222

中断是一种协作机制,一个线程不能强制其他线程停止正在执行的操作而去执行其他操作。

什么是中断状态?

线程类有一个描述自身是否被中断了的boolean类型的状态,可以通过调用 .isInterrupted() 方法来查看。官方解释如下:

简单来说,这个方法如果返回 true ,那么表示线程已经被中断

恢复中断

这里提到的 “恢复中断” 绝对不是 “从中断中恢复” 的意思!

在《Java并发编程实战》一书第五章 p78页,首次提到了这个恢复中断的概念,而当我看到第七章的时候才明白这里为什么要恢复中断。

因为中断是一种协作机制,当一个线程阻塞时,我们需要通过另一个线程调用阻塞线程的 interrupt() 方法,来请求阻塞线程取消任务。最简单的阻塞方法就是 Thread.sleep() , 我们来看一下我写的一个简单的例子:

public class Demo_01 {

    public static void main(String[] args) throws InterruptedException {
        
        Thread myTh = new Thread(new TaskDemo());
        
        myTh.start();
        TimeUnit.SECONDS.sleep(3);
        // 中断myTh线程
        myTh.interrupt();
    }
}

class TaskDemo implements Runnable {
    @Override
    public void run() {
        try {
            TimeUnit.SECONDS.sleep(10);
        } catch (InterruptedException e) {
            System.out.println("捕获到中断异常,当前线程的中断状态是:" + Thread.currentThread().isInterrupted());
            System.out.println("即将恢复中断... ...");
            Thread.currentThread().interrupt();
            System.out.println("中断恢复!中断状态已经是:" + Thread.currentThread().isInterrupted());
        }
    }
}

执行结果是:

我们可以看到,interrupt()方法会将线程的中断状态置为true,而任务被中断的时候不仅会抛出一个InterruptedException异常,还会清除中断状态

这个问题在书中第七章 P114 有所说明:

阻塞库方法,例如Thread.sleep和Object.wait等,都会检查线程何时中断,并且在发现中断时提前返回。它们在响应中断时执行的操作包括:清除中断状态;抛出InterruptedException,表示阻塞操作由于中断而提前结束。

上面的程序中,由于TaskDemo实现Runnable接口,在面对中断请求的时候,无法向上层抛出,必须捕获,如果没有在catch块中调用interrupt()方法,那么中断状态将在清除之后被上层逻辑 “屏蔽”。书中强调,一个健壮的任务执行方法,应该能够正确处理中断请求,而不是屏蔽

因此,如果不想任务执行时出现的中断被屏蔽,就必须将线程的中断状态恢复,换句话说,就是再次将线程的中断状态置为true!

因为有点绕,所以大多数人可能完全无视了这个问题,导致我在搜索这个恢复中断的问题时,页面里全都是些如何从中断的状态中恢复过来,真的很无语。

总结

调用线程的interrupt()方法可以向一个阻塞中的线程发出中断请求,其原理就是将线程的中断状态设置为true。

阻塞的线程在收到中断请求的时候,会执行两步操作:清除中断状态,抛出中断异常(InterruptedException)。

这就导致了在一些无法向调用者继续抛出中断异常的情况下,如实现了Runnable接口,必须在run()方法内部进行中断异常的捕获,从而导致了上层调用者可能无法正确获得线程的中断状态,导致没有相应的处理措施,即为中断被屏蔽。

因此,在这种情况下,为了避免任务内部屏蔽了中断请求(注意,屏蔽中断请求并不意味着任务没有响应中断),需要通过在catch块中重新调用任务所在线程的interrupt()方法,恢复到中断状态,来告诉上层调用者,“我是一个已经被中断的线程”。

综上,就是关于《Java并发编程实战》中“恢复中断”的相关理解,欢迎文末留言。

猜你喜欢

转载自blog.csdn.net/u014745069/article/details/87889222