基于本文回答

播面 播面

文图音视,全方位拆解八股文
0
评论

interrupt()、interrupted() 和 isInterrupted() 方法的区别是什么?

知识点图片

在 Java 的多线程编程中,interrupt()interrupted()isInterrupted() 都与线程中断机制有关。理解它们的区别,核心在于理解“中断状态”(Interrupt Status/Flag)这个概念。

简单来说,Java 的中断是一种协作机制,调用中断方法并不会立刻强行停止目标线程,而是给目标线程设置一个“中断标志”,目标线程需要自己去检查这个标志并决定如何处理。

以下是这三个方法的详细区别:


1. interrupt() —— “发出中断请求”

  • 方法类型:实例方法 (Thread 类的非静态方法)。
  • 作用对象:调用该方法的线程对象(例如 thread.interrupt() 作用于 thread 线程)。
  • 功能设置线程的中断标志为 true
  • 特殊情况:如果目标线程正处于阻塞状态(例如调用了 Thread.sleep()Object.wait()Thread.join() 等),调用 interrupt() 会让目标线程立刻抛出 InterruptedException 异常,并且中断标志会被立刻清除(重置为 false

2. isInterrupted() —— “查看中断状态(只看不改)”

  • 方法类型:实例方法 (Thread 类的非静态方法)。
  • 作用对象:调用该方法的线程对象(例如 thread.isInterrupted() 检查 thread 线程的状态)。
  • 功能返回线程当前的中断状态(truefalse
  • 是否清除标志。无论调用多少次,它只是读取状态,绝不改变中断标志的值。

3. interrupted() —— “查看并清除中断状态(看完就删)”

  • 方法类型静态方法 (Thread.interrupted())。
  • 作用对象当前正在执行此代码的线程(即 Thread.currentThread())。
  • 功能返回当前线程的中断状态,并且将中断标志位清除(重置为 false
  • 是否清除标志。如果连续调用两次该方法,第二次一定会返回 false(除非在两次调用之间线程再次被中断)。

📝 核心对比总结表

方法名 方法类型 作用于哪个线程 主要功能 是否清除中断标志位?
interrupt() 实例方法 具体的线程对象 打断该线程(设置标志为 true) (但抛出 InterruptedException 时会被底层清除)
isInterrupted() 实例方法 具体的线程对象 判断该线程是否被中断
interrupted() 静态方法 当前运行的线程 判断当前线程是否被中断 (检查后立刻设为 false)

💻 代码示例与场景分析

场景 1:isInterrupted()interrupted() 的对比

java
public class InterruptDemo {
    public static void main(String[] args) {
        Thread.currentThread().interrupt(); // 中断主线程自己

        // 此时主线程的中断标志为 true

        // isInterrupted() 只读取,不清除
        System.out.println(Thread.currentThread().isInterrupted()); // 输出 true
        System.out.println(Thread.currentThread().isInterrupted()); // 输出 true

        // interrupted() 读取并清除
        System.out.println(Thread.interrupted()); // 输出 true (读取到了中断状态,随后将其清除为 false)
        System.out.println(Thread.interrupted()); // 输出 false (状态已经被上一步清除了)
    }
}

场景 2:抛出 InterruptedException 时的陷阱(非常重要)

当你捕获了 InterruptedException 后,线程的中断标志会被底层自动清除(变成 false)。如果你不重新中断,上层代码将无法感知到这个线程曾经被中断过。

java
Thread thread = new Thread(() -> {
    while (!Thread.currentThread().isInterrupted()) {
        try {
            // 模拟耗时操作
            Thread.sleep(1000); 
        } catch (InterruptedException e) {
            // 注意:此时发生异常,中断标志位已经被自动清除了(变成了 false)
            
            // 【正确做法】:重新设置中断标志,让外层的 while 循环能感知到中断并退出
            Thread.currentThread().interrupt(); 
            
            System.out.println("线程在睡眠时被中断,准备退出");
        }
    }
});

thread.start();
Thread.sleep(500); // 让子线程先飞一会儿
thread.interrupt(); // 中断子线程

💡 总结口诀

  • interrupt()去打断别人(或自己)。
  • isInterrupted()悄悄看别人(或自己)有没有被打断。
  • interrupted()看自己有没有被打断,看完顺手把痕迹抹掉
00:00
00:00