interrupted、interrupt、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并清除标志位,需手动重新设置标志位才能让线程感知中断。
百流积聚,江河是也;文若化风,可以砾石。

浙公网安备 33010602011771号