引言

你真的会用线程中断吗?很多人觉得调用 interrupt() 就能直接停止线程,结果写出来的代码要么线程停不下来,要么莫名抛出异常。我在某物流轨迹同步项目中踩过一个大坑:用 while(true) 写的同步线程,想通过 interrupt() 停止,却因为没判断中断状态,线程一直死循环,导致服务器线程数暴增到 3000+,最终触发 OOM。还有个支付项目,同事在线程里捕获了 InterruptedException 后没做任何处理,中断信号被 “吞掉”,导致超时的支付任务无法终止,一直占用数据库连接,高峰时直接拖慢整个服务。你可能也遇过类似困惑:为什么 interrupt() 有时候有用有时候没用?中断状态该怎么正确判断?读完这篇,你能吃透 interrupt() 的核心逻辑,掌握中断状态判断的正确姿势,避开线程中断的常见陷阱,写出能优雅停止的多线程代码。

从 “interrupt () 能直接停止线程” 的误解开始:为什么很多人用错中断?

曾经我也以为,只要调用线程的 interrupt() 方法,线程就会立刻停止。直到一次线上故障排查,我发现一段 “看似没问题” 的线程代码,无论怎么调用 interrupt() 都停不下来。后来才明白,我完全误解了 interrupt() 的作用。

很多初学者容易犯的错是:把 interrupt() 当成 “强制停止线程” 的开关,却不知道它的真实作用是 “给线程发一个中断通知”—— 线程接不接收、什么时候处理这个通知,全看线程自身的逻辑。就像你给正在工作的同事发消息说 “该下班了”,同事可能立刻停下,也可能把手头的活做完再停,甚至假装没看见(如果代码里没判断中断状态)。

用两段代码对比下,你一看就懂:

java

运行

// 错误认知:调用interrupt()就能直接停止线程
public class WrongInterruptUsage {
    public static void main(String[] args) throws InterruptedException {
        Thread taskThread = new Thread(() -> {
            // 死循环,没判断中断状态,interrupt()无效
            while (true) {
                System.out.println("任务执行中...");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // 捕获异常后没做任何处理,中断信号被“吞掉”
                    System.out.println("捕获到异常,但继续执行");
                }
            }
        });
        taskThread.start();
        Thread.sleep(3000);
        // 以为调用后线程会停止,实际无效
        taskThread.interrupt();
    }
}

java

运行

// 正确理解:interrupt()发通知,线程需主动判断中断状态并响应
public class CorrectInterruptUsage {
    public static void main(String[] args) throws InterruptedException {
        Thread taskThread = new Thread(() -> {
            // 循环条件判断中断状态,收到通知后退出
            while (!Thread.currentThread().isInterrupted()) {
                System.out.println("任务执行中...");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // 1. 重新设置中断状态(sleep会清除中断状态)
                    Thread.currentThread().interrupt();
                    // 2. 退出循环,停止线程
                    break;
                }
            }
            System.out.println("线程收到中断通知,已停止");
        });
        taskThread.start();
        Thread.sleep(3000);
        taskThread.interrupt();
    }
}

说白了,线程中断的核心逻辑是 “协作式停止”——interrupt() 只负责发 “停止通知”,线程必须主动检查通知(判断中断状态),并自己决定什么时候停止。这也是为什么很多人用错中断:把 “发通知” 当成了 “强制执行”,忽略了线程内部的响应逻辑。

为什么中断状态判断常出错?从原理到正确姿势

这里有个容易被忽视的点:很多人知道要判断中断状态,却分不清 isInterrupted() 和 interrupted() 的区别,也不知道 sleep()wait() 这些方法会清除中断状态。我在某监控项目中见过,同事用 interrupted() 判断中断状态,结果因为它会清除状态,导致后续逻辑无法感知中断,线程明明该停却继续运行。

线程中断的原理其实很简单,用 “办公场景” 的比喻再梳理一遍:

  1. 每个线程都有一个 “中断状态”(布尔值,默认 false),就像每个员工都有一个 “是否下班” 的状态标识。
  2. 调用 interrupt() 方法,本质是把这个状态设为 true(发 “下班通知”),不会直接让线程停止。
  3. 线程内部需要定期检查这个状态:如果是 true,就执行停止逻辑(收拾东西下班);如果是 false,就继续工作。
  4. 有些方法(sleep()wait()join())会 “响应中断”—— 如果线程在这些方法中阻塞时收到中断通知,会抛出 InterruptedException,并且自动清除中断状态(相当于 “收到通知但不小心忘了”)。

这里用表格清晰区分两个核心判断方法:

方法 作用 是否清除中断状态 适用场景
isInterrupted() 判断当前线程的中断状态 线程内部判断是否需要停止
interrupted() 判断当前线程的中断状态 清除中断状态(极少使用)

用一段代码展示中断状态的变化过程,帮你直观理解:

java

运行

// Java 8+
public class InterruptStatusDemo {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            System.out.println("初始中断状态:" + Thread.currentThread().isInterrupted());
            // 收到中断通知,状态变为true
            Thread.currentThread().interrupt();
            System.out.println("调用interrupt()后状态:" + Thread.currentThread().isInterrupted());
            // interrupted()判断后会清除状态
            System.out.println("interrupted()判断结果:" + Thread.interrupted());
            System.out.println("清除后中断状态:" + Thread.currentThread().isInterrupted());
        });
        thread.start();
        thread.join();
    }
}

执行结果:

plaintext

初始中断状态:false
调用interrupt()后状态:true
interrupted()判断结果:true
清除后中断状态:false

💡 提示:这段代码清晰展示了中断状态的变化 ——interrupt() 设为 true,interrupted() 判断后重置为 false。实际开发中,99% 的场景都该用 isInterrupted(),避免 interrupted() 不小心清除状态导致后续逻辑出错。

实战代码:从基础到生产级,吃透线程中断的正确用法

示例 1(基础):interrupt () 核心用法与中断状态判断

java

运行

// Java 8+
public class InterruptBasicUsage {
    public static void main(String[] args) throws InterruptedException {
        // 1. 创建线程,在循环中检查中断状态
        Thread taskThread = new Thread(() -> {
            // 关键:用isInterrupted()判断,不清除状态
            while (!Thread.currentThread().isInterrupted()) {
                System.out.println("执行核心任务...");
                try {
                    // sleep()会响应中断,抛出InterruptedException
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    System.out.println("收到中断通知,正在停止线程...");
                    // 必须重新设置中断状态:sleep会清除状态,不重置的话循环会继续
                    Thread.currentThread().interrupt();
                }
            }
            System.out.println("线程已停止,最终中断状态:" + Thread.currentThread().isInterrupted());
        });

        // 2. 启动线程
        taskThread.start();
        // 3. 主线程等待3秒后,发送中断通知
        Thread.sleep(3000);
        System.out.println("主线程发送中断通知");
        taskThread.interrupt();

        // 4. 等待线程停止
        taskThread.join();
        System.out.println("主线程执行完毕");
    }
}

执行结果:

plaintext

执行核心任务...
执行核心任务...
执行核心任务...
执行核心任务...
执行核心任务...
执行核心任务...
主线程发送中断通知
收到中断通知,正在停止线程...
线程已停止,最终中断状态:true
主线程执行完毕

💡 提示:这段代码的核心是 “正确响应中断”—— 在循环中用 isInterrupted() 判断状态,捕获 InterruptedException 后重新设置中断状态,确保循环能退出。如果不重新设置,sleep() 清除状态后,isInterrupted() 会返回 false,循环会继续运行,线程永远停不下来。

示例 2(进阶):生产级异步任务的优雅停止

java

运行

// Java 17+ 生产级异步任务:用中断实现优雅停止
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class GracefulShutdownWithInterrupt {
    // 虚拟线程池(Java 17+特性):轻量级,适合高并发异步任务
    private final ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();
    // 运行状态:volatile保证可见性,配合中断实现优雅停止
    private volatile boolean running = true;

    // 提交异步任务
    public void submitTask(String taskId) {
        if (!running) {
            throw new IllegalStateException("任务池已关闭");
        }
        executor.submit(() -> {
            try {
                // 任务执行中定期检查中断状态
                while (!Thread.currentThread().isInterrupted() && running) {
                    System.out.println("执行任务:" + taskId + ",处理中...");
                    // 模拟任务处理耗时
                    TimeUnit.MILLISECONDS.sleep(200);
                }
                if (Thread.currentThread().isInterrupted()) {
                    System.out.println("任务" + taskId + "收到中断通知,停止执行");
                }
            } catch (InterruptedException e) {
                // 响应中断,清理资源
                System.out.println("任务" + taskId + "被中断,清理资源后退出");
                // 重新设置中断状态,确保后续逻辑能感知
                Thread.currentThread().interrupt();
            }
        });
    }

    // 优雅停止:先停止接收新任务,再中断所有正在执行的任务
    public void shutdown() throws InterruptedException {
        running = false;
        // 1. 停止接收新任务
        executor.shutdownNow();
        // 2. 等待任务停止,最多等待5秒
        if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
            System.err.println("部分任务未正常停止,强制关闭");
        } else {
            System.out.println("所有任务已停止,任务池关闭完成");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        GracefulShutdownWithInterrupt taskPool = new GracefulShutdownWithInterrupt();
        // 提交3个任务
        for (int i = 0; i < 3; i++) {
            taskPool.submitTask("T" + i);
        }
        // 运行3秒后停止
        TimeUnit.SECONDS.sleep(3);
        System.out.println("开始关闭任务池...");
        taskPool.shutdown();
    }
}

执行结果(部分):

plaintext

执行任务:T0,处理中...
执行任务:T1,处理中...
执行任务:T2,处理中...
...
开始关闭任务池...
任务T0收到中断通知,停止执行
任务T1被中断,清理资源后退出
任务T2收到中断通知,停止执行
所有任务已停止,任务池关闭完成

💡 提示:这个模式的核心优势是 “优雅 + 安全”—— 用 running 标志控制任务接收,用中断通知正在执行的任务停止;配合 shutdownNow() 批量中断线程池中的任务,确保任务能清理资源后再退出,避免资源泄漏。

示例 3(踩坑示范):忽略 InterruptedException 导致中断失效

错误代码

java

运行

// Java 8+ 错误写法:捕获InterruptedException后未处理,中断信号被“吞掉”
public class IgnoreInterruptedException {
    public static void main(String[] args) throws InterruptedException {
        Thread taskThread = new Thread(() -> {
            while (!Thread.currentThread().isInterrupted()) {
                System.out.println("执行任务...");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // 错误:只打印日志,没重新设置中断状态,也没退出
                    System.out.println("捕获到异常,但继续执行");
                }
            }
            System.out.println("线程停止");
        });

        taskThread.start();
        Thread.sleep(3000);
        taskThread.interrupt();
        // 等待线程停止(实际永远不会停止)
        taskThread.join();
    }
}

执行结果(问题表现):

plaintext

执行任务...
执行任务...
执行任务...
捕获到异常,但继续执行
执行任务...
执行任务...
...(无限循环)

❌ 为什么错:sleep() 被中断后会抛出 InterruptedException,并且自动清除中断状态。这里只捕获异常打印日志,既没重新设置中断状态,也没退出循环 ——isInterrupted() 会返回 false,循环继续运行,线程永远停不下来。⚠️ 后果:我在某数据同步项目中见过这个问题,定时同步线程因为这样的代码,收到中断通知后无法停止,导致新的同步任务启动后,旧线程还在运行,两个线程同时操作数据库,引发数据重复问题。

正确做法

java

运行

// Java 8+ 正确写法:捕获InterruptedException后,重新设置中断状态并退出
public class HandleInterruptedException {
    public static void main(String[] args) throws InterruptedException {
        Thread taskThread = new Thread(() -> {
            while (!Thread.currentThread().isInterrupted()) {
                System.out.println("执行任务...");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    System.out.println("收到中断通知,准备停止...");
                    // 1. 重新设置中断状态,确保isInterrupted()能感知
                    Thread.currentThread().interrupt();
                    // 2. 退出循环,停止线程(也可做资源清理)
                    break;
                }
            }
            System.out.println("线程已停止");
        });

        taskThread.start();
        Thread.sleep(3000);
        taskThread.interrupt();
        taskThread.join();
    }
}

执行结果(正确表现):

plaintext

执行任务...
执行任务...
执行任务...
收到中断通知,准备停止...
线程已停止

💡 提示:处理 InterruptedException 时,核心是 “不吞掉中断信号”—— 要么重新设置中断状态,让循环条件能感知;要么直接退出线程。实际开发中,还可以在退出前添加资源清理逻辑(比如关闭数据库连接、释放文件句柄),确保任务停止后不遗留资源。

示例 4(最佳实践):Java 21+ 生产级中断处理规范写法

java

运行

// Java 21+ 生产级规范写法:结合结构化并发、中断响应、异常分级处理
import java.time.Duration;
import java.util.concurrent.StructuredTaskScope;
import java.util.concurrent.TimeoutException;

public class ProductionInterruptBestPractice {
    // 真实场景:用户下单任务,支持中断和超时控制
    public String createOrder(String userId, String productId) throws Exception {
        // 结构化并发(Java 21+转正):自动管理线程生命周期,配合中断实现优雅停止
        try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
            // 提交核心任务:扣减库存
            var stockTask = scope.fork(() -> deductStock(productId));
            // 提交核心任务:扣减余额
            var balanceTask = scope.fork(() -> deductBalance(userId));

            // 超时控制:3秒内未完成则中断所有任务
            if (!scope.joinUntil(Duration.ofSeconds(3))) {
                throw new TimeoutException("下单超时,已中断所有任务");
            }

            // 处理中断相关异常
            scope.throwIfFailed(ex -> ex instanceof InterruptedException);

            return "下单成功!订单ID:" + generateOrderId() +
                    ",剩余库存:" + stockTask.get() +
                    ",剩余余额:" + balanceTask.get();
        }
    }

    // 扣减库存:响应中断,清理中间状态
    private Integer deductStock(String productId) throws InterruptedException {
        try {
            System.out.println("开始扣减库存:" + productId);
            // 模拟库存扣减耗时,支持中断
            for (int i = 0; i < 5; i++) {
                if (Thread.currentThread().isInterrupted()) {
                    System.out.println("库存扣减被中断,回滚库存状态");
                    throw new InterruptedException("库存扣减任务中断");
                }
                TimeUnit.MILLISECONDS.sleep(300);
            }
            return 99; // 扣减后剩余库存
        } catch (InterruptedException e) {
            // 重新抛出,让上层统一处理
            throw e;
        }
    }

    // 扣减余额:响应中断
    private Integer deductBalance(String userId) throws InterruptedException {
        System.out.println("开始扣减余额:" + userId);
        if (Thread.currentThread().isInterrupted()) {
            throw new InterruptedException("余额扣减任务中断");
        }
        TimeUnit.MILLISECONDS.sleep(500);
        return 1000; // 扣减后剩余余额
    }

    private String generateOrderId() {
        return "ORDER_" + System.currentTimeMillis();
    }

    public static void main(String[] args) {
        try {
            ProductionInterruptBestPractice demo = new ProductionInterruptBestPractice();
            System.out.println(demo.createOrder("U1001", "P2002"));
        } catch (Exception e) {
            System.err.println("下单失败:" + e.getMessage());
        }
    }
}

执行结果:

plaintext

开始扣减库存:P2002
开始扣减余额:U1001
下单成功!订单ID:ORDER_1735790000000,剩余库存:99,剩余余额:1000

💡 提示:这个写法的核心是 “协同中断 + 统一管控”—— 结合结构化并发自动中断子任务,每个核心任务主动检查中断状态并响应;上层统一处理中断相关异常,确保任务中断后能回滚中间状态,避免数据不一致。

易错点与避坑指南:我见过的 5 个真实中断相关 bug

❌ 常见错误 1:捕获 InterruptedException 后未重新设置中断状态

  • 错误代码示例:

java

运行

// 错误写法:吞掉中断信号,线程无法停止
public class SwallowInterruptSignal {
    public void task() {
        while (!Thread.currentThread().isInterrupted()) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // 只打印日志,未重置中断状态
                System.out.println("发生中断异常");
            }
        }
    }
}
  • 实际场景:我在某定时任务项目中见过这个问题,定时任务线程需要在凌晨 3 点停止,调用 interrupt() 后,因为异常被吞掉,线程一直运行到早上 8 点,导致新的定时任务启动后,数据处理出现冲突。
  • 根本原因:InterruptedException 被捕获后,中断状态会被清除,isInterrupted() 返回 false,循环继续运行;中断信号相当于被 “吞掉”,线程无法感知中断。
  • ✓ 正确做法:捕获异常后,要么重新设置中断状态,要么直接退出线程:

java

运行

public class CorrectInterruptHandle {
    public void task() {
        while (!Thread.currentThread().isInterrupted()) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                System.out.println("发生中断异常");
                Thread.currentThread().interrupt(); // 重新设置中断状态
                break; // 退出线程
            }
        }
    }
}
  • 防守方案:编码规范强制要求,捕获 InterruptedException 后必须处理(重置状态或退出);用代码扫描工具检测 “吞掉中断异常” 的写法。

❌ 常见错误 2:用 Thread.interrupted () 误清除中断状态

  • 错误代码示例:

java

运行

// 错误写法:用interrupted()清除了中断状态
public class WrongInterruptMethod {
    public void task() {
        while (true) {
            // interrupted()判断后会清除状态,后续逻辑无法感知
            if (Thread.interrupted()) {
                break;
            }
            System.out.println("执行任务...");
        }
        // 这里中断状态已被清除,返回false
        System.out.println("中断状态:" + Thread.currentThread().isInterrupted());
    }
}
  • 实际场景:我带的实习生写的代码里出现过这个问题,线程虽然退出了循环,但后续的资源清理逻辑需要判断中断状态,结果因为状态被清除,清理逻辑没执行,导致数据库连接没关闭,出现连接泄漏。
  • 根本原因:对 interrupted() 和 isInterrupted() 的语义理解不清 ——interrupted() 是 “一次性判断”,会清除中断状态,适合临时检查并清除状态的场景;大部分业务场景需要的是 “只判断不清除”,应该用 isInterrupted()
  • ✓ 正确做法:业务逻辑中判断中断状态,优先用 isInterrupted()

java

运行

public class CorrectInterruptMethod {
    public void task() {
        while (!Thread.currentThread().isInterrupted()) {
            System.out.println("执行任务...");
        }
        // 中断状态仍为true,后续逻辑可感知
        System.out.println("中断状态:" + Thread.currentThread().isInterrupted());
    }
}
  • 防守方案:编码规范明确 interrupted() 的使用场景,禁止在业务循环中用它判断中断状态;代码评审时重点检查中断方法的选择。

❌ 常见错误 3:认为 interrupt () 能停止不响应中断的线程

  • 错误代码示例:

java

运行

// 错误写法:线程内无中断判断,interrupt()无效
public class UnresponsiveInterrupt {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            // 死循环,没有任何中断判断
            while (true) {
                System.out.println("执行任务...");
            }
        });
        thread.start();
        Thread.sleep(3000);
        thread.interrupt(); // 无效,线程不会停止
    }
}
  • 实际场景:我在某视频转码项目中见过这个问题,转码线程用了无限循环且没判断中断状态,用户触发 “取消转码” 后,线程一直运行,占用 CPU 和内存,导致后续转码任务排队堵塞。
  • 根本原因:interrupt() 的作用是 “发通知”,不是 “强制停止”。如果线程内部没有任何中断判断逻辑(不检查 isInterrupted(),也不调用会响应中断的方法),中断信号就像 “石沉大海”,线程永远不会停止。
  • ✓ 正确做法:线程内部必须定期检查中断状态,或调用能响应中断的方法(sleep()wait() 等):

java

运行

public class ResponsiveInterrupt {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            while (!Thread.currentThread().isInterrupted()) {
                System.out.println("执行任务...");
            }
            System.out.println("线程已停止");
        });
        thread.start();
        Thread.sleep(3000);
        thread.interrupt();
    }
}
  • 防守方案:编码规范要求,所有长期运行的线程必须包含中断判断逻辑;用线程池管理线程,避免直接创建 “不可中断” 的线程。

❌ 常见错误 4:用 stop () 方法替代 interrupt ()(已废弃)

  • 错误代码示例:

java

运行

// 错误写法:用已废弃的stop()方法停止线程
public class UseStopInsteadOfInterrupt {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            while (true) {
                System.out.println("执行任务...");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        thread.start();
        Thread.sleep(3000);
        thread.stop(); // 已废弃,强制停止线程
    }
}
  • 实际场景:我在维护一个老项目时见过这个问题,用 stop() 停止文件写入线程,导致文件写入不完整,出现损坏;而且 stop() 会释放线程持有的锁,可能引发数据不一致。
  • 根本原因:stop() 是强制停止线程,相当于 “直接断电”,线程没有机会清理资源(比如关闭文件、回滚数据库),容易导致资源泄漏和数据损坏;Java 1.2 就已废弃这个方法,不推荐使用。
  • ✓ 正确做法:用 interrupt() 配合中断判断,实现 “优雅停止”:

java

运行

public class UseInterruptCorrectly {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            while (!Thread.currentThread().isInterrupted()) {
                System.out.println("执行任务...");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    System.out.println("清理资源后停止");
                    Thread.currentThread().interrupt();
                }
            }
        });
        thread.start();
        Thread.sleep(3000);
        thread.interrupt();
    }
}
  • 防守方案:用代码扫描工具禁止使用 stop()suspend() 等废弃的线程控制方法;老项目重构时,将 stop() 替换为 interrupt() 实现优雅停止。

❌ 常见错误 5:多线程共享中断状态,导致逻辑混乱

  • 错误代码示例:

java

运行

// 错误写法:多个线程共享同一个中断状态标识
public class ShareInterruptStatus {
    private volatile boolean interrupted = false;

    public void startTasks() {
        // 线程1
        new Thread(() -> {
            while (!interrupted) {
                System.out.println("线程1执行任务...");
            }
        }).start();

        // 线程2
        new Thread(() -> {
            while (!interrupted) {
                System.out.println("线程2执行任务...");
            }
        }).start();

        // 触发中断,两个线程同时停止
        interrupted = true;
    }
}
  • 实际场景:我在某分布式任务调度项目中见过这个问题,用共享变量控制多个任务线程的停止,结果因为一个线程处理异常需要继续运行,却被共享变量的 “中断状态” 强制停止,导致任务执行不完整。
  • 根本原因:每个线程都有自己的中断状态,用共享变量替代线程自身的中断状态,会导致 “一断全断”,无法实现单个线程的精准控制;而且共享变量的可见性和原子性难以保证,容易出现控制失效。
  • ✓ 正确做法:使用线程自身的中断状态,或给每个线程单独设置控制标识:

java

运行

public class PerThreadInterruptControl {
    private volatile boolean thread1Running = true;
    private volatile boolean thread2Running = true;

    public void startTasks() {
        // 线程1:独立控制
        Thread thread1 = new Thread(() -> {
            while (thread1Running && !Thread.currentThread().isInterrupted()) {
                System.out.println("线程1执行任务...");
            }
        });
        thread1.start();

        // 线程2:独立控制
        Thread thread2 = new Thread(() -> {
            while (thread2Running && !Thread.currentThread().isInterrupted()) {
                System.out.println("线程2执行任务...");
            }
        });
        thread2.start();

        // 只停止线程1,线程2继续运行
        thread1Running = false;
        thread1.interrupt();
    }
}
  • 防守方案:编码规范禁止用共享变量统一控制多个线程的中断;如需精准控制单个线程,使用线程自身的中断状态或独立的控制标识。

总结与延伸

快速回顾:① interrupt() 是发中断通知而非强制停止线程;② 必须主动判断中断状态(优先 isInterrupted())并响应;③ 捕获 InterruptedException 后需重置状态或退出。延伸学习:① 中断与结构化并发的协同使用;② 虚拟线程的中断机制;③ 中断异常的分级处理框架。面试备准:1. Q:interrupt() 的作用是什么?A:给线程发中断通知,不直接停止线程;2. Q:isInterrupted() 和 interrupted() 的区别?A:前者不清除中断状态,后者清除;3. Q:sleep() 被中断后会发生什么?A:抛出 InterruptedException 并清除中断状态;4. Q:为什么不推荐用 stop() 停止线程?A:强制停止,无法清理资源,易导致数据损坏;5. Q:如何实现线程的优雅停止?A:用 interrupt() 发通知,线程内部定期检查中断状态,捕获异常后清理资源并退出。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐