Go Worker Pool 的两种思路实现
· 阅读需 8 分钟
写带结果收集的 worker pool,任务分发通常不难。真正容易写岔的是怎么停。
停之前先把这两个问题答死,后面实现几乎是顺水推舟:
- 已经进队、还没被 worker 拿走的任务,还要不要做?
- 已经做完、结果还没发出去的任务,结果能不能丢?
对这两个问题的回答不同,中断机制和 API 形态就会分叉。下面按这两种答案,分别看实现。
一、先定语义,再选手段
| 维度 | A:取消优先 | B:排空优先 |
|---|---|---|
| 中断信号 | 主要靠 context 取消 | 取消 + close(taskQueue) |
| 已入队未执行 | 放弃 | 继续取完并执行 |
| 已算出的结果 | 取消时可以丢 | 必须发出去 |
| worker 退出 | select 听 ctx.Done() | for range 排空后退出 |
| 是否 close 任务队列 | 通常不关 | 要关 |
| 典型场景 | 超时、用户取消、快速失败 | 批处理、提交过的任务都要有交代 |
没有谁绝对更好,只是「停止」的含义不同:
- A:别干了,能停就停。
- B:不再接新活,但手里已接的活要做完(至少要给出结果)。