如何停止一个正在运行的线程?
- 使用标志位(flag):最安全和最推荐的方式是 使用一个共享变量作为标志位,通过改变这个标志位的值,来通知线程应该停止运行
- 线程需要定期检查这个标志位,并在必要时退出
public class SafeStopThread implements Runnable {
//这里使用了volatile关键字,确保变量的修改对所有线程可见
private volatile boolean running = true;
public void run() {
while (running) {
// 执行任务
}
// 清理资源
}
public void stopRunning() {
running = false;
}
}
- 中断机制:Java提供中断机制,允许一个线程停止另一个线程的运行
- 通过调用线程对象(Thread)的
interrupt()方法,可以请求终止线程
- 通过调用线程对象(Thread)的
中断机制的三个函数的解读
- 调用
Thread.interrupt()来中断一个线程,就会设置中断标识为 true - 当中断线程调用静态方法
Thread.interrupted()来检查中断状态时,中断状态会被清零 - 非静态方法
isInterrupted()用来查询其它线程的中断状态,且不会改变中断状态标识
简单的说,就是任何抛出InterruptedException异常的方法,都会将中断状态清零
public class InterruptibleThread implements Runnable {
public void run() {
try {
while (!Thread.currentThread().isInterrupted()) {
// 线程的工作逻辑
}
} catch (InterruptedException e) {
// 处理中断异常,清理资源
Thread.currentThread().interrupt(); // 保留中断状态
}
}
}
- 避免使用
stop()暴力停止:方法已弃用,强制让线程停止有可能使一些请理性的工作得不到完成
sleep和wait的区别?
| 特性 | sleep() | wait() |
|---|---|---|
| 所属类 | Thread 类(静态方法) | Object 类(实例方法) |
| 锁释放 | ❌ | ✅ |
| 使用前提 | 任意位置调用 | 必须在同步块内或同步方法内(持有锁) |
| 唤醒机制 | 超时自动恢复 | 需 notify()/notifyAll() 或超时 |
| 设计用途 | 暂停线程执行,不涉及锁协作 | 线程间协调,释放锁让其他线程工作 |
- 所属分类不同:sleep()可以在任何地方直接通过
Thread.sleep()调用,无需依赖对象实例;wait()必须通过创建对象实例来调用 - 锁释放的情况:在
sleep期间,其他线程无法获得该线程持有的锁;Object.wait():调用该方法时,线程会释放持有的对象锁,进入等待状态,直到其它线程调用相同对象唤醒它 - 唤醒机制:sleep 休眠时间结束后,线程 自动恢复 到就绪状态,等待CPU调度;wait 需要其他线程调用相同对象的
notify()或notifyAll()方法才能被唤醒notify()会随机唤醒一个在该对象上等待的线程notifyAll()会唤醒所有在该对象上等待的线程