interrupted、interrupt、isInterrupted三者关系如何界定?

摘要:interrupted、interrupt、isInterrupted 三者关系全解析 在 Java 线程中断机制中,interrupt()、interrupted()、isInterrupted() 是核心且极易混淆的三个方法,它们围绕线
interrupted、interrupt、isInterrupted 三者关系全解析 在 Java 线程中断机制中,interrupt()、interrupted()、isInterrupted() 是核心且极易混淆的三个方法,它们围绕线程中断标志位工作,但职责、行为、调用方式完全不同。下面从「核心概念→方法拆解→对比→实战场景」层层讲透。 一、先理解核心:线程中断标志位 Java 中的“中断”不是强制终止线程,而是给线程设置一个布尔类型的中断标志位(线程内部的一个状态): 线程本身可以感知这个标志位,决定是否停止执行(是“协作式”而非“强制式”); 当线程处于 sleep()、wait()、join() 等阻塞状态时,若被中断,会抛出 InterruptedException,并清除中断标志位(标志位变回 false); 三个方法的核心区别,本质是对这个标志位的「设置」「查询」「查询并清除」的不同操作。 二、逐个拆解三个方法 1. interrupt():设置中断标志位(核心动作) 核心定义 public void interrupt() 属于 Thread 类的实例方法,作用是给目标线程设置中断标志位为 true(仅设置标志,不直接终止线程)。 关键特性 调用方式:通过线程对象调用(如 thread.interrupt()),作用于该线程; 特殊场景:若目标线程正处于阻塞状态(sleep/wait/join),会立即抛出 InterruptedException,并清除中断标志位(标志位变回 false); 无返回值:仅执行“设置标志”动作,不返回任何结果。 示例代码 public class InterruptDemo { public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(() -> { // 循环检测中断标志位 while (!Thread.currentThread().isInterrupted()) { System.out.println("线程运行中..."); try { Thread.sleep(500); // 阻塞状态 } catch (InterruptedException e) { System.out.println("捕获到中断异常,此时标志位:" + Thread.currentThread().isInterrupted()); // 若想让线程退出,需手动再次设置中断标志(因为异常会清除标志) Thread.currentThread().interrupt(); } } System.out.println("线程退出,最终标志位:" + Thread.currentThread().isInterrupted()); }); t1.start(); Thread.sleep(2000); // 主线程等待2秒 t1.interrupt(); // 给t1设置中断标志 } } 输出结果: 线程运行中... 线程运行中... 线程运行中... 捕获到中断异常,此时标志位:false 线程退出,最终标志位:true 2. isInterrupted():查询中断标志位(不清除) 核心定义 public boolean isInterrupted() 属于 Thread 类的实例方法,作用是查询目标线程的中断标志位状态,不会修改标志位。 关键特性 调用方式:通过线程对象调用(如 thread.isInterrupted()); 返回值:true(已中断)/ false(未中断); 核心区别:仅查询,不改变标志位状态(这是和 interrupted() 的核心差异)。 示例代码 public class IsInterruptedDemo { public static void main(String[] args) { Thread t1 = new Thread(() -> { int i = 0; while (i < 5) { System.out.println("t1运行中,标志位:" + Thread.currentThread().isInterrupted()); i++; try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } }); t1.start(); // 主线程1秒后给t1设置中断 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } t1.interrupt(); } } 输出结果(关键看标志位变化): t1运行中,标志位:false t1运行中,标志位:false t1运行中,标志位:true // 中断后标志位变为true t1运行中,标志位:true t1运行中,标志位:true 3. interrupted():查询并清除中断标志位(静态方法) 核心定义 public static boolean Thread.interrupted() 属于 Thread 类的静态方法,作用是: 查询当前线程的中断标志位状态; 立即清除中断标志位(将标志位重置为 false)。 关键特性 调用方式:Thread.interrupted()(静态方法,作用于当前线程); 返回值:返回清除前的标志位状态(true 表示之前是中断状态,false 表示不是); 核心坑点: 仅作用于当前线程(调用该方法的线程),而非目标线程; 执行后一定会清除标志位(即使之前是 true,执行后变为 false)。 示例代码 public class InterruptedDemo { public static void main(String[] args) { Thread t1 = new Thread(() -> { // 给当前线程设置中断标志 Thread.currentThread().interrupt(); // 第一次调用:查询并清除标志位(返回true,清除后变为false) System.out.println("第一次interrupted():" + Thread.interrupted()); // 第二次调用:标志位已被清除,返回false System.out.println("第二次interrupted():" + Thread.interrupted()); // isInterrupted()仅查询,此时标志位是false System.out.println("isInterrupted():" + Thread.currentThread().isInterrupted()); }); t1.start(); } } 输出结果: 第一次interrupted():true 第二次interrupted():false isInterrupted():false 三、三者核心对比表 方法名 类型 核心作用 是否清除中断标志 作用对象 返回值 interrupt() 实例方法 设置中断标志位为true 否(阻塞时会清) 目标线程 无 isInterrupted() 实例方法 查询中断标志位状态 否 目标线程 boolean interrupted() 静态方法 查询并清除当前线程的中断标志位 是 当前线程 boolean 四、实战场景:正确使用中断机制 场景1:优雅停止线程(推荐方式) public class StopThreadGracefully { public static void main(String[] args) throws InterruptedException { Thread worker = new Thread(() -> { // 循环检测中断标志 while (!Thread.currentThread().isInterrupted()) { System.out.println("执行任务中..."); try { Thread.sleep(1000); // 模拟任务耗时 } catch (InterruptedException e) { System.out.println("任务被中断,准备退出"); // 重新设置中断标志(因为sleep抛出异常会清除标志) Thread.currentThread().interrupt(); } } System.out.println("线程已优雅退出"); }); worker.start(); Thread.sleep(3000); // 主线程等待3秒 worker.interrupt(); // 触发中断 } } 场景2:避免误用 interrupted() // 错误示例:用interrupted()查询其他线程的状态(无效,因为它只作用于当前线程) Thread t1 = new Thread(() -> {}); t1.interrupt(); System.out.println(Thread.interrupted()); // false(作用于主线程,而非t1) System.out.println(t1.isInterrupted()); // true(正确查询t1的状态) 总结 核心本质:三者围绕「线程中断标志位」工作,interrupt() 是“设置标志”,isInterrupted() 是“只读查询”,interrupted() 是“查询并清空”; 关键差异:interrupted() 是静态方法(作用于当前线程)且会清除标志位,isInterrupted() 是实例方法(作用于目标线程)且仅查询; 阻塞场景:sleep/wait/join 等阻塞方法被中断时,会抛出 InterruptedException 并清除标志位,需手动重新设置标志位才能让线程感知中断。