Java中如何控制两个不可并行、按指定时长交替运行的线程?
Java实现寺庙队列交替放行的解决方案
核心思路
- 靠
ReentrantLock互斥锁把A、B的放行逻辑锁死,同一时间只能跑一个,彻底避免并行开放 - 每个队列的放行任务最多跑10分钟,要是中途队列空了就提前结束
- 用一个循环来交替触发A、B的放行,直到两队都没人了才停
代码实现
直接上可运行的代码,注释里写清楚逻辑:
import java.util.LinkedList; import java.util.Queue; import java.util.concurrent.locks.ReentrantLock; public class TempleQueueManager { // 模拟A、B两个等待队列 private final Queue<String> queueA = new LinkedList<>(); private final Queue<String> queueB = new LinkedList<>(); // 互斥锁,保证同一时间只有一个队列能放行 private final ReentrantLock accessLock = new ReentrantLock(); // 往A队列加人 public void addPersonToA(String person) { queueA.add(person); } // 往B队列加人 public void addPersonToB(String person) { queueB.add(person); } // 处理指定队列,最多跑maxDuration毫秒(这里就是10分钟) private void processQueue(Queue<String> targetQueue, long maxDuration) { accessLock.lock(); try { long startTimestamp = System.currentTimeMillis(); // 只要队列还有人,且没到10分钟就继续放行 while (!targetQueue.isEmpty() && (System.currentTimeMillis() - startTimestamp) < maxDuration) { String person = targetQueue.poll(); System.out.println("放行:" + person); // 模拟每放一个人耗时100ms,实际场景替换成真实的放行逻辑 Thread.sleep(100); } } catch (InterruptedException e) { // 线程被中断时恢复中断状态 Thread.currentThread().interrupt(); } finally { // 不管成功失败,最后都要释放锁 accessLock.unlock(); } } // 启动交替放行流程 public void startAlternatingRelease() { final long TEN_MINUTES = 10 * 60 * 1000; // 10分钟转成毫秒数 // 循环直到两个队列都空了 while (!queueA.isEmpty() || !queueB.isEmpty()) { // 先处理A队列(如果还有人) if (!queueA.isEmpty()) { processQueue(queueA, TEN_MINUTES); } // 再处理B队列(如果还有人) if (!queueB.isEmpty()) { processQueue(queueB, TEN_MINUTES); } } System.out.println("所有人员都放完了"); } public static void main(String[] args) { TempleQueueManager manager = new TempleQueueManager(); // 模拟往两个队列各加200人 for (int i = 1; i <= 200; i++) { manager.addPersonToA("A队-" + i); manager.addPersonToB("B队-" + i); } // 启动放行 manager.startAlternatingRelease(); } }
关键细节解释
- 互斥锁
ReentrantLock:processQueue方法加锁后,不管是A还是B队列调用,同一时间只能有一个在执行,完美解决并行问题 - 时长控制:通过记录开始时间,每次循环都检查是否超过10分钟,要是队列提前空了也会自动停止,不会白等
- 交替逻辑:循环里先看A队有没有人,有就处理10分钟;再看B队,有就处理10分钟,直到两队都空
可选优化方向
- 要是不想阻塞主线程,可以把
startAlternatingRelease放到单独的线程里跑 - 如果场景是动态加人(比如放行过程中还有人来),可以用
Condition来实现等待唤醒,没人的时候线程休眠,有人加进来再唤醒继续放行 - 要是需要更精准的定时中断,也可以结合
ScheduledExecutorService来定时打断当前的放行任务,但记得要和锁配合好,避免锁冲突
内容的提问来源于stack exchange,提问作者Harish Selvam
相关产品推荐
相关产品推荐

