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

为事件循环类游戏开发带优先级队列的单线程Executor

实现建议:自定义分层队列+手动单线程事件循环

针对你的需求,JDK自带的Executor框架无法直接满足所有规则(尤其是Hard任务入队清空其他任务、Normal任务优先时完全忽略Soft任务的逻辑),最适合的方案是手动实现单线程事件循环,配合三个分层的任务队列,比基于Executor扩展更灵活可控。

核心思路

维护三个独立的线程安全队列,分别对应Soft、Normal、Hard任务,单线程循环按以下优先级顺序处理:

  1. 优先处理Hard任务:只要Hard队列有任务,先清空Soft和Normal队列,然后执行Hard任务(自然阻塞线程直到玩家完成操作)
  2. 无Hard任务时,处理Normal队列:只执行Normal任务,完全跳过Soft任务
  3. 无Normal任务时,再处理Soft队列

代码示例(Java)

// 定义任务优先级枚举
enum TaskPriority {
    SOFT, NORMAL, HARD
}

// 游戏任务抽象类
abstract class GameTask {
    final TaskPriority priority;
    GameTask(TaskPriority priority) {
        this.priority = priority;
    }
    abstract void execute();
}

// 单线程事件循环实现
public class GameEventLoop extends Thread {
    private final BlockingQueue<GameTask> softQueue = new LinkedBlockingQueue<>();
    private final BlockingQueue<GameTask> normalQueue = new LinkedBlockingQueue<>();
    private final BlockingQueue<GameTask> hardQueue = new LinkedBlockingQueue<>();
    private volatile boolean isRunning = true;

    // 外部提交任务的入口方法
    public void submitTask(GameTask task) {
        switch (task.priority) {
            case SOFT -> softQueue.offer(task);
            case NORMAL -> normalQueue.offer(task);
            case HARD -> hardQueue.offer(task);
        }
    }

    @Override
    public void run() {
        while (isRunning) {
            // 1. 优先处理Hard任务
            GameTask hardTask = hardQueue.poll();
            if (hardTask != null) {
                // 清空所有低优先级任务队列
                softQueue.clear();
                normalQueue.clear();
                // 执行Hard任务,线程会阻塞直到玩家操作完成
                hardTask.execute();
                continue;
            }

            // 2. 处理Normal任务
            GameTask normalTask = normalQueue.poll();
            if (normalTask != null) {
                normalTask.execute();
                continue;
            }

            // 3. 处理Soft任务
            GameTask softTask = softQueue.poll();
            if (softTask != null) {
                softTask.execute();
                continue;
            }

            // 无任务时休眠,避免CPU空转
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                isRunning = false;
            }
        }
    }

    // 停止事件循环的方法
    public void shutdown() {
        isRunning = false;
        this.interrupt();
    }
}

关键细节说明

  • 线程安全:使用LinkedBlockingQueue保证多线程提交任务时的线程安全,消费端仅单线程处理,无需额外加锁。
  • Hard任务阻塞:只要GameTask的execute()方法内部实现阻塞逻辑(比如调用Object.wait()等待玩家触发唤醒,或者UI库的阻塞对话框),单线程会自然停在该任务上,直到玩家操作完成。
  • 灵活性:手动事件循环可以轻松扩展其他规则(比如任务超时、批量处理等),比依赖Executor的黑盒封装更适配游戏场景。

备选方案:扩展ThreadPoolExecutor(不推荐)

如果一定要基于Executor框架实现,可以自定义BlockingQueue并重写offer()方法:当添加Hard任务时,先清空队列中所有Soft/Normal任务,同时队列的排序逻辑保证Hard>Normal>Soft。但这种方式需要处理ThreadPoolExecutor的内部锁机制,逻辑复杂且灵活性不足,仅适合必须依赖Executor的场景。

内容的提问来源于stack exchange,提问作者Fraser

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 02:50:34