You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 18:38:24