1. 引言

本文将探讨在Java中安全停止线程的方法——这并不简单,因为Thread.stop()方法已被废弃。根据Oracle官方说明stop()可能导致被监控的对象损坏。

⚠️ 关键问题:直接调用stop()会引发不可预测的状态破坏,必须避免使用!

2. 使用标志位控制

先看一个基础线程类示例,该线程不会自行终止,我们需要外部干预:

public class ControlSubThread implements Runnable {

    private Thread worker;
    private final AtomicBoolean running = new AtomicBoolean(false);
    private int interval;

    public ControlSubThread(int sleepInterval) {
        interval = sleepInterval;
    }
 
    public void start() {
        worker = new Thread(this);
        worker.start();
    }
 
    public void stop() {
        running.set(false);
    }

    public void run() { 
        running.set(true);
        while (running.get()) {
            try { 
                Thread.sleep(interval); 
            } catch (InterruptedException e){ 
                Thread.currentThread().interrupt();
                System.out.println(
                  "线程被中断,操作未完成");
            }
            // 执行业务逻辑 
         } 
    } 
}

核心改进

  • AtomicBoolean替代while(true)循环
  • 通过running标志位控制线程生命周期
  • 避免多线程环境下的竞态条件(参考原子变量详解

3. 线程中断机制

当线程处于长时休眠或等待不可释放的时,标志位控制可能失效:

潜在风险:线程可能长时间阻塞甚至无法正常终止

此时需要结合中断机制,升级实现:

public class ControlSubThread implements Runnable {

    private Thread worker;
    private AtomicBoolean running = new AtomicBoolean(false);
    private AtomicBoolean stopped = new AtomicBoolean(false);
    private int interval;

    // ... 其他方法同前 ...

    public void interrupt() {
        running.set(false);
        worker.interrupt();
    }

    boolean isRunning() {
        return running.get();
    }

    boolean isStopped() {
        return stopped.get();
    }

    public void run() {
        running.set(true);
        stopped.set(false);
        while (running.get()) {
            try {
                Thread.sleep(interval);
            } catch (InterruptedException e){
                Thread.currentThread().interrupt();
                System.out.println(
                  "线程被中断,操作未完成");
            }
            // 执行业务逻辑
        }
        stopped.set(true);
    }
}

🔧 中断机制要点

  1. interrupt()方法同时设置标志位和调用线程中断
  2. 当线程处于sleep()/wait()等阻塞状态时,会立即抛出InterruptedException
  3. 中断后线程会跳出循环(因running已为false)
  4. 通过isStopped()可确认终止状态

4. 总结

本文展示了两种安全停止线程的方案:

  • 基础方案:使用AtomicBoolean标志位
  • 进阶方案:标志位 + interrupt()组合

最佳实践

  • 永远不要使用已废弃的stop()方法
  • 优先使用标志位控制
  • 对可能阻塞的操作增加中断处理
  • 通过Atomic*类保证线程安全

完整代码示例见GitHub仓库


原始标题:How to Kill a Java Thread | Baeldung

» 下一篇: Java ArrayDeque 详解