线程的中断

59 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第5天,点击查看活动详情

1、Java 中的中断和操作系统的中断还不一样,这里就按照状态来理解吧,不要和操作系统的中断联系在一起

2、记住中断只是一个状态,Java的方法可以选择对这个中断进行响应,也可以选择不响应。响应的意思就是写相对应的代码执行相对应的操作,不响应的意思就是什么代码都不写。

  1. isInterrupted: Thread 类中的实例方法,持有线程实例引用即可检测线程中断状态

  2. interrupted:

    1. Thread 中的静态方法,检测调用这个方法的线程是否已经中断
    2. 注意:这个方法返回中断状态的同时,会将此线程的中断状态重置为 false 如果我们连续调用两次这个方法的话,第二次的返回值肯定就是 false
  3. interrupt: Thread 类中的实例方法,用于设置一个线程的中断状态为 true

isInterrupted()方法这个会清除中断状态

为什么要这么设置呢?原因在于:

  • interrupted()是一个静态方法,可以在Runnable接口实例中使用
  • isInterrupted()是一个Thread的实例方法,在重写Thread的run方法时使用
public class ThreadInterrupt {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            System.out.println(Thread.interrupted());
        });  //这个new Thread用的是runnable接口那个构造函数

        Thread t2 = new Thread(){
            @Override
            public void run() {
                System.out.println(isInterrupted());
            }
        };//这个new Thread用的就是Thread的空参构造

    }
}

重难点

当然,中断除了是线程状态外,还有其他含义,否则也不需要专门搞一个这个概念出来了。

初学者肯定以为 thread.interrupt() 方法是用来暂停线程的,主要是和它对应中文翻译的“中断”有关。中断在并发中是常用的手段,请大家一定好好掌握。可以将中断理解为线程的状态,它的特殊之处在于设置了中断状态为 true 后,这几个方法会感知到:

  1. wait(), wait(long), wait(long, int), join(), join(long), join(long, int), sleep(long), sleep(long, int)

    这些方法都有一个共同之处,方法签名上都有throws InterruptedException,这个就是用来响应中断状态修改的。

  2. 如果线程阻塞在 InterruptibleChannel 类的 IO 操作中,那么这个 channel 会被关闭。

  3. 如果线程阻塞在一个 Selector 中,那么 select 方法会立即返回。

对于以上 3 种情况是最特殊的,因为他们能自动感知到中断(这里说自动,当然也是基于底层实现),并且在做出相应的操作后都会重置中断状态为 false。然后执行相应的操作(通常就是跳到 catch 异常处)。

如果不是以上3种情况,那么,线程的 interrupt() 方法被调用,会将线程的中断状态设置为 true。

那是不是只有以上 3 种方法能自动感知到中断呢?不是的,如果线程阻塞在 LockSupport.park(Object obj) 方法,也叫挂起,这个时候的中断也会导致线程唤醒,但是唤醒后不会重置中断状态,所以唤醒后去检测中断状态将是 true。

资料: Oracle官方文档 —> The Java® Language Specification Java SE 8 Edition —> 第17章 Threads and Locks