4、经典调度算法:先来先服务(FCFS)、最短作业优先(SJF)、优先级调度、轮转调度(RR)
调度算法这东西,说白了就是「谁先干活」的问题。
我在分拣机项目里调试过不下十种调度策略,踩过的坑比写过的代码还多。今天聊的这四种算法,是操作系统里的老面孔,但放在工业分拣场景下,每个都有它的脾气。
4.1 先来先服务(FCFS)
这是最朴素的算法。谁先到,谁先干。就像排队买饭,先来的先打菜。
核心逻辑:
- 任务按到达时间排序
- 非抢占式——一旦开始,必须做完
- 实现简单,几乎零开销
分拣场景适用性:
适合包裹到达顺序稳定、处理时间差异不大的产线。比如快递分拣,每个包裹重量相近,处理时间差不多,FCFS完全够用。
⚠ 避坑指南:
我曾经在一个异形件分拣线上用了FCFS,结果一个大件卡了30秒,后面所有小件全部堵死。平均等待时间直接爆炸。记住:FCFS怕「长任务堵车」。
4.2 最短作业优先(SJF)
这个算法很聪明——谁干得快,谁先上。
你想想看,如果有个小件只需要2秒处理完,你非要等前面那个大件磨蹭20秒,是不是很亏?SJF就是解决这个问题的。
两种变体:
- 非抢占式SJF:等当前任务做完,再挑最短的下一个
- 抢占式SJF(SRTF):新来的任务如果更短,直接抢断当前任务
| 特性 | 非抢占式SJF | 抢占式SRTF |
|---|---|---|
| 平均等待时间 | 较短 | 最短(理论最优) |
| 实现复杂度 | 低 | 高(需要保存上下文) |
| 分拣适用性 | 适合已知处理时间的场景 | 适合实时性要求高的场景 |
💡 我的经验:
在分拣机里,我一般用非抢占式SJF。因为抢占式需要频繁保存机械臂的当前位置和状态,搞不好会丢包。嗯,这里要注意:SJF需要预估处理时间,不准的话反而更糟。
4.3 优先级调度
这个就有点「看人下菜碟」的意思了。
每个任务带一个优先级数字,数字越小优先级越高(或者反过来,看你怎么定义)。调度器每次挑优先级最高的任务执行。
优先级怎么定?
- 静态优先级:任务创建时就定死。比如VIP包裹永远优先
- 动态优先级:运行时可以调整。比如等太久的任务自动升优先级
分拣场景实战:
我记得有个冷链分拣项目,生鲜包裹必须15分钟内处理完,否则变质。我给这些包裹设了最高优先级,普通包裹排后面。效果立竿见影,损耗率从8%降到0.5%。
⚠ 致命陷阱:
优先级调度最大的坑是「饥饿」——低优先级任务永远轮不到。我曾经见过一个低优先级包裹在传送带上转了3小时没人管。解决方案?用「老化」机制,等得越久优先级越高。
4.4 轮转调度(RR)
这个算法最公平。每个任务分一个时间片,轮流执行。时间一到,不管干没干完,先让给下一个。
你想想看,就像开会发言,每人3分钟,时间到了换下一个人。虽然可能话没说完,但至少每个人都有机会说。
关键参数:时间片大小
| 时间片 | 优点 | 缺点 |
|---|---|---|
| 太大(如100ms) | 上下文切换少 | 接近FCFS,响应慢 |
| 太小(如1ms) | 响应快,公平 | 切换开销大,CPU利用率低 |
| 适中(如10-20ms) | 平衡 | 需要调优 |
💡 我的调优经验:
在分拣机里,我一般把时间片设为机械臂完成一次抓取动作的时间。这样每个包裹至少能完成一个完整动作,不会出现「抓了一半又放下」的尴尬情况。时间片设得太小,机械臂会像抽风一样来回抖动。
4.5 四种算法对比总结
| 算法 | 平均等待时间 | 公平性 | 实现难度 | 分拣推荐度 |
|---|---|---|---|---|
| FCFS | 差 | 好(按到达顺序) | ★☆☆☆☆ | ★★☆☆☆ |
| SJF | 优 | 差(长任务吃亏) | ★★★☆☆ | ★★★★☆ |
| 优先级 | 取决于优先级定义 | 差(可能饥饿) | ★★☆☆☆ | ★★★★★(有老化机制时) |
| RR | 中等 | 最好 | ★★☆☆☆ | ★★★☆☆ |
我的最终建议:
没有银弹。我在实际项目中,经常是「混合调度」——用优先级做粗调度,用RR做细调度。比如VIP包裹优先,同优先级内用轮转。这样既保证了关键任务不耽误,又防止了低优先级饿死。
说白了,调度算法是门平衡的艺术。你追求公平,就牺牲效率;你追求效率,就可能不公平。选哪个?看你的业务场景说话。
下一章我会讲实时调度算法,那才是分拣机这种硬实时系统的真正考验。到时候再聊。