Apollo 技术文档Apollo 技术文档
指南
  • 架构概述
  • BigWorld 架构深度解析
  • BigWorld 进程架构与玩家生命周期
  • AOI九宫格系统详解
  • AOI广播与消息去重
  • Base 模块
  • Core 模块
  • Runtime 模块
  • Data 模块
  • Network 模块
  • /modules/actor.html
  • Game 模块
  • BigWorld 模块
服务器应用
API 参考
QA
GitHub
指南
  • 架构概述
  • BigWorld 架构深度解析
  • BigWorld 进程架构与玩家生命周期
  • AOI九宫格系统详解
  • AOI广播与消息去重
  • Base 模块
  • Core 模块
  • Runtime 模块
  • Data 模块
  • Network 模块
  • /modules/actor.html
  • Game 模块
  • BigWorld 模块
服务器应用
API 参考
QA
GitHub
  • MMORPG 架构 QA

Q75: 线程池如何设计?任务如何调度?

核心结论

线程池的价值不是“把所有任务都扔进去并发跑”,而是给一类可并行任务提供受控的执行资源。

真正需要先设计的是:

  • 哪些任务适合线程池
  • 任务是 CPU 型还是 I/O 型
  • 队列满了怎么办
  • 执行顺序和优先级如何保证

如果这些边界不清晰,线程池很容易变成隐藏延迟和资源争用的黑盒。

一、线程池真正适合什么任务

常见更适合线程池的是:

  • 后台 I/O
  • 压缩和序列化
  • 数据库任务
  • 非实时统计和离线处理

不太适合直接扔进通用线程池的通常是:

  • 强顺序状态机任务
  • 需要单对象串行推进的逻辑
  • 主战斗链路中的高一致性对象更新

二、线程池不是越大越好

线程数过多常见问题包括:

  • 上下文切换增加
  • 锁竞争加重
  • cache locality 变差
  • 线程空转

所以线程池大小通常应围绕:

  • CPU 核数
  • 任务类型
  • 外部依赖阻塞比例

而不是“能开多少开多少”。

三、任务队列设计比线程数更关键

线程池系统通常真正容易出问题的不是线程,而是队列:

  • 入队过快
  • 出队跟不上
  • 优先级混乱
  • 长任务阻塞短任务

所以必须明确:

  • 队列是否有界
  • 是否分优先级
  • 是否分不同任务类型独立队列

四、调度要先分清任务类型

1. CPU 型任务

更关注:

  • 核心数利用
  • 避免过度切换

2. I/O 型任务

更关注:

  • 阻塞等待
  • 超时控制
  • 回调或结果投递

把这两类任务混在一个池里,经常会互相拖累。

五、结果回传路径也要设计

线程池不是“任务跑完就结束”,还要回答:

  • 结果交给谁
  • 是否切回主线程或拥有者线程
  • 失败如何传播

如果这层不清晰,线程池只是在把复杂度往调用方甩。

六、工程上更稳妥的做法

常见做法是:

  • 线程池按任务类型拆分
  • 队列有界并带背压策略
  • 长任务和短任务分离
  • 结果统一回投到权威线程或事件循环

这样才能避免“池很忙,但系统更慢”的情况。

七、常见误区

1. 线程池就是并发提速器

不对。它只能提升适合并行的任务,不能替代边界清晰的并发设计。

2. 所有阻塞操作都丢线程池就行

如果没有限流和分级,只会把阻塞堆到另一个地方。

3. 一个全局线程池最简单

简单,但很容易让不同任务类型互相干扰。

参考资料

  • 线程池调度、背压和异步任务回投实践资料
在 GitHub 上编辑此页
最后更新: 3/20/26, 6:06 AM
贡献者: cuihairu