1. 不要用的方法
1.1 Thread.stop()
- 早已废弃 (
@Deprecated
),会直接释放线程持有的所有锁。 - 可能导致对象处于不一致状态(例如正在写一个共享变量,被 stop 中断,数据可能损坏)。
- 可能引发死锁或数据不一致。
1.2 Thread.suspend()
/ Thread.resume()
- 同样已废弃,容易在持锁时挂起线程,导致永久死锁。
2. 推荐的线程停止方式
Java 规范倡导所谓 "协作式中断" (Cooperative Interruption):
→ 不强制杀死线程,而是给线程一个信号,让它自己停下来。
核心思路:
- 外部线程设置某种"停止标记"或调用
interrupt()
。 - 线程内部定期检查标记,当检测到需要停止时,自己安全退出。
2.1 方法一:使用标志位
java
public class StopThreadDemo implements Runnable {
private volatile boolean stopRequested = false;
public void stop() { stopRequested = true; }
@Override public void run() {
while (!stopRequested) { // 线程工作 System.out.println("线程运行中...");
try { Thread.sleep(500); }
catch (InterruptedException e) { // 如果需要响应中断,可在这里 break
Thread.currentThread().interrupt(); // 保留中断状态 } }
System.out.println("线程安全停止"); }
public static void main(String[] args) throws InterruptedException {
StopThreadDemo task = new StopThreadDemo();
Thread t = new Thread(task);
t.start();
Thread.sleep(2000);
task.stop(); // 通知线程停止 } }
要点:
volatile
确保多线程可见性,避免被编译器优化成缓存变量。- 线程内部必须自己在循环条件中检查
stopRequested
。
2.2 方法二:使用 interrupt()
+ 检查中断状态
当线程处于阻塞状态(sleep()
、wait()
、join()
)时,调用 interrupt()
会抛 InterruptedException
。
java
public class InterruptDemo implements Runnable {
@Override public void run() {
while (!Thread.currentThread().isInterrupted()) {
System.out.println("线程运行中...");
try {
Thread.sleep(500); }
catch (InterruptedException e) {
System.out.println("线程被中断,准备停止...");
Thread.currentThread().interrupt(); // 重新设置中断状态(因为异常会清除中断标记)
break; } }
System.out.println("线程安全退出"); }
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(new InterruptDemo());
t.start(); Thread.sleep(2000);
t.interrupt(); // 通知线程停止(协作式) } }
要点:
interrupt()
并不会强制杀死线程,而是给线程一个 中断标记。- 对阻塞方法,
interrupt()
会让它抛InterruptedException
。 - 线程必须捕获并自己退出(或在循环判断中断标记时退出)。
2.3 方法三:结合 ExecutorService
提交任务
使用 线程池 API,可以优雅地停止线程:
java
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<?> future = executor.submit(() -> {
try {
while (!Thread.currentThread().isInterrupted()) { // 工作代码
Thread.sleep(500); } }
catch (InterruptedException e) {
Thread.currentThread().interrupt();
} });
Thread.sleep(2000);
future.cancel(true); // true 表示试图中断线程 executor.shutdown();
future.cancel(true)
相当于调用底层线程的interrupt()
。
3. 底层原理
- 每个线程对象里有一个 中断标志位 (
interrupted
)。 interrupt()
只是把标志位置为true
,对阻塞方法则会抛InterruptedException
。Thread.interrupted()
:静态方法,返回当前线程的中断状态,并清除标志位。isInterrupted()
:实例方法,查询线程的中断状态,不会清除标志。