一、没有中断机制代码会出什么问题假设 Java 没有interrupt()你要怎么让一个正在运行的线程停下来方案 1用一个volatile boolean标志位class Worker implements Runnable { private volatile boolean running true; public void stop() { running false; } Override public void run() { while (running) { // 做任务 } } }问题在哪如果线程正在Thread.sleep(10000)睡了 10 秒你调用了stop()把running改成false线程要睡满 10 秒才会醒来检查running。这 10 秒内它什么都干不了也无法响应你的停止请求。方案 2用Thread.stop()Java 已废弃这个方法能强制杀死线程但问题更严重线程可能在写文件、操作数据库、持有锁强制杀死会导致资源泄漏、数据损坏、锁永远不释放。所以 Java 设计者面临一个矛盾不能强制杀太危险不能光用标志位线程阻塞时无法及时响应于是interrupt()被设计出来它不是强制停止而是礼貌地通知线程有人希望你停下来你自己决定什么时候停。二、interrupt()的核心设计协作式中断interrupt()的设计哲学是发通知不强制。它只做三件事给目标线程设置一个中断标志位true如果目标线程正在sleep()/wait()/join()立刻唤醒它并抛出InterruptedException如果线程正在正常运行它不会自动停止需要你手动检查中断状态为什么这样设计因为线程最清楚自己什么时候是安全的停止点。比如// 线程正在执行转账操作 // 1. 从 A 账户扣款 // 2. 向 B 账户加款 // 如果在这两步之间被强制中断钱扣了但没加上数据就不一致了。 // 所以线程自己决定等这两步原子操作做完再检查中断标志安全退出。三、代码实战三种场景场景 1线程在正常运行你调用interrupt()public class InterruptDemo { public static void main(String[] args) throws InterruptedException { Thread worker new Thread(() - { // 模拟一个长时间运行的任务 for (int i 0; i 100000; i) { // isInterrupted() 检查有人让我中断吗 if (Thread.currentThread().isInterrupted()) { System.out.println(收到中断信号我在第 i 次循环时安全退出); return; // 自己决定在这里停 } // 做一些计算... } }); worker.start(); Thread.sleep(100); // 主线程等 100ms worker.interrupt(); // 发送中断请求 } }输出收到中断信号我在第 xxx 次循环时安全退出关键点interrupt()只是设了个标志线程通过isInterrupted()主动检查什么时候停由线程自己决定这就是协作式场景 2线程在sleep()你调用interrupt()public class SleepInterruptDemo { public static void main(String[] args) { Thread sleeper new Thread(() - { try { System.out.println(我要睡 10 秒...); Thread.sleep(10000); System.out.println(睡醒了); // 这行不会执行 } catch (InterruptedException e) { System.out.println(sleep 期间被中断了异常信息 e.getMessage()); // 注意catch 之后中断标志位会被清空变成 false System.out.println(catch 后中断标志 Thread.currentThread().isInterrupted()); } }); sleeper.start(); // 主线程等 500ms 后中断它 try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } sleeper.interrupt(); } }输出我要睡 10 秒... sleep 期间被中断了异常信息sleep interrupted catch 后中断标志false设计原因如果线程在sleep()它无法执行isInterrupted()检查所以 JVM 设计成收到中断时立刻抛异常强制线程醒来但抛异常后中断标志会被清除这是 Java 的设计约定防止你重复处理场景 3线程在wait()你调用interrupt()public class WaitInterruptDemo { private static final Object lock new Object(); public static void main(String[] args) { Thread waiter new Thread(() - { synchronized (lock) { try { System.out.println(我要 wait 了...); lock.wait(); // 释放锁进入等待 System.out.println(被 notify 了); // 不会执行 } catch (InterruptedException e) { System.out.println(wait 期间被中断了); // 同样中断标志会被清除 } } }); waiter.start(); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } waiter.interrupt(); // 中断 wait 中的线程 } }输出我要 wait 了... wait 期间被中断了和sleep()的区别sleep()不释放锁抱着锁睡觉wait()会释放锁进等待队列但两者被中断时都会立刻抛InterruptedException并清除中断标志四、一个容易踩的坑中断标志被清除了怎么办看这段代码while (!Thread.currentThread().isInterrupted()) { try { doWork(); Thread.sleep(1000); // 假设这里被中断 } catch (InterruptedException e) { // 异常被吞掉什么都不做 // 糟糕中断标志已经被清除了 } } // 因为标志被清除循环会继续执行线程永远停不下来正确做法在catch里重新设置中断标志或者干脆退出while (!Thread.currentThread().isInterrupted()) { try { doWork(); Thread.sleep(1000); } catch (InterruptedException e) { // 方案 A重新设置标志让上层处理 Thread.currentThread().interrupt(); // 方案 B直接 break/return在这里处理退出 break; } }五、总结一张图看懂逻辑主线程调用 t.interrupt() │ ▼ ┌─────────────────┐ │ 设置 t 的中断标志位 true │ └─────────────────┘ │ ├──► 如果 t 正在运行 ──► t 自己用 isInterrupted() 检查 │ │ │ ▼ │ 决定什么时候安全退出 │ ├──► 如果 t 正在 sleep()/wait()/join() │ ▼ 立刻唤醒抛 InterruptedException │ ▼ 中断标志位被自动清除变回 false │ ▼ 在 catch 里要么重新 interrupt()要么 break/return六、核心要点记住这几条就够了方法作用注意t.interrupt()给线程 t 发中断请求只是请求不强制Thread.interrupted()检查当前线程是否被中断并清除标志静态方法会清标志t.isInterrupted()检查线程 t 是否被中断不清除标志实例方法sleep/wait/join被中断立刻抛InterruptedException抛完后标志位变false设计的本质interrupt()提供了一种既能唤醒阻塞线程又不强制破坏其执行逻辑的安全机制。没有它你要么无法及时停止阻塞线程要么只能用危险的强制手段。