reentrantlock 配合 condition 和阻塞队列可实现任务有序串行执行,核心是分离入队与执行、用锁保状态一致、用条件变量协调唤醒;需用 while 循环检查守卫条件,支持公平锁和中断感知;若无需定制逻辑,推荐使用 newsinglethreadexecutor。

ReentrantLock 本身不提供队列有序化能力,但可配合 Condition 和 显式队列(如 LinkedBlockingQueue 或自定义 FIFO 队列) 实现任务的有序提交与串行执行。关键在于分离“入队”和“执行”逻辑,用锁保障状态一致性,用条件变量协调等待与唤醒。
用 ReentrantLock + Condition 控制单线程执行序列
适合需要严格按提交顺序逐个执行、且不允许并发执行的场景(如资源独占型任务)。核心思路是:只允许一个线程在临界区中执行任务,其余任务排队等待。
- 定义一个 ReentrantLock 和对应的 Condition(例如
taskCompleted),用于通知下一个等待者 - 维护一个阻塞队列(如
LinkedBlockingQueue<runnable></runnable>)暂存待执行任务 - 每次提交任务时加锁入队;若当前无正在执行的任务,则启动执行线程(或直接执行)
- 执行完一个任务后,唤醒等待线程——它会检查队列是否为空,非空则取下一个并继续执行
避免虚假唤醒与重复执行
使用 Condition 的 await() 必须放在 while 循环中判断守卫条件,否则可能因中断或虚假唤醒导致跳过检查。
- 守卫条件通常是“队列是否为空”或“是否有任务正在运行”
- 示例守卫写法:
while (taskQueue.isEmpty() || isRunning) { condition.await(); } - 每次 signal() 前确保已修改守卫状态(如出队、置 isRunning=false),否则唤醒无效
支持公平性与中断感知
ReentrantLock 构造时传入 true 可启用公平模式,使等待线程按 FIFO 获取锁,增强任务执行顺序的可预测性。
- 公平锁能减少线程饥饿,但吞吐量略低;非公平锁性能更好,但顺序不保证
- 使用
lockInterruptibly()替代lock(),使等待线程可响应中断 - 任务 Runnable 内部也应定期检查
Thread.interrupted(),及时退出长耗时操作
轻量级替代:用单线程 ExecutorService 更简洁
如果只需串行执行且不需定制唤醒逻辑,Executors.newSingleThreadExecutor() 是更简单可靠的选择。
- 它内部基于 LinkedBlockingQueue + 无限循环 Worker 线程,天然保序
- 自动处理异常、线程复用、优雅关闭等细节,不易出错
- 仅当需要与外部状态深度耦合(如结合业务锁、动态启停、混合同步策略)时,才需手写 ReentrantLock 方案
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











