用一个小实验,理解 Worker 的退出边界
创建、消息入队、处理与退出。把时间顺序展开,观察消息与资源有效期之间的关系。
并发模块中的很多边界问题,都需要回到一个具体问题:某个操作发生时,接收它的对象还处于什么状态?
本站的 Worker 生命周期实验 将创建、发送、处理和退出分成独立步骤。每一步都由手动操作推进,方便重复观察相同的顺序。
先观察四个状态
实验中,Worker 有四个状态:未创建、运行中、退出中和已退出。
| 状态 | 可以做什么 | 需要关注什么 |
|---|---|---|
| 未创建 | 创建实例 | 消息接收对象尚不存在 |
| 运行中 | 发送消息、处理消息、请求退出 | 接收条件与队列顺序 |
| 退出中 | 完成退出 | 新操作是否还允许进入 |
| 已退出 | 重新创建 | 新旧实例是否能够区分 |
这张表是演示的规则。真实运行时可能存在更多内部状态,接口允许的操作也可能不同。
发送成功与处理完成是两个步骤
先创建 Worker,连续发送两条消息。它们会进入队列,此时“已处理”仍然为零。点击“处理下一条”后,队列中的第一条消息才会被取出。
在这个模型里,发送的结果表示消息进入了队列。处理结果则需要观察后续步骤。将两者分别记录,才能说明消息当前处于什么阶段。
// 用于解释本页模型的伪代码,不是具体运行时的实现。
bool send(Message message) {
if (state != Running) {
return false;
}
pending.push(message);
return true;
}
可以用这组操作观察:创建 → 发送两次 → 处理一次。此时队列中剩余一条,日志中有两次入队和一次处理记录。
请求退出时,队列如何处理
本实验选择一种清晰的退出策略:进入退出中后停止接收消息,并取消尚未处理的消息。 每条取消记录都包含消息编号和实例编号。
这样做便于观察退出边界。它不意味着所有 Worker 都应当采用相同策略:具体系统可能排空队列、取消任务,或为不同类型的任务提供不同约定。
阅读真实实现时,应先确认退出策略,再检查状态变化、消息处理与资源释放是否满足该策略。
用实例编号区分新旧上下文
退出后重新创建,实例编号会增加。新的消息与新的实例关联,日志仍然保留旧实例的事件。
这让一个容易被忽略的问题变得可见:名称相同的 Worker,在不同创建周期内属于不同实例。分析消息和回调时,需要知道它们属于哪个创建周期。
一组可以重复的观察步骤
- 创建实例,发送两条消息。
- 处理第一条,核对队列与日志。
- 请求退出,观察第二条消息被取消。
- 确认发送按钮已禁用,再完成退出。
- 重新创建,观察实例编号变化。
- 点击重置,恢复初始状态。
实验不执行实际的 C++ 线程,也不进行性能测量。它将状态、消息和退出策略拆开,作为理解工程边界的一个起点。
相关项目:OpenHarmony Worker。