8-5.【OC】【NSOperation】NSOperation 的优先级是如何影响调度的?优先级是硬约束还是软提示?与 QoS 的区别?

5 阅读3分钟

NSOperation 的世界里,优先级决定了谁能“插队”,但它并不是万能的。理解它的运作机制需要区分 队列内优先级系统级资源分配


1. 优先级是硬约束还是软提示?

NSOperationqueuePriority 属性是一个典型的软提示(Soft Hint)

调度的真实逻辑:

  1. 就绪过滤OperationQueue 首先筛选出所有 isReady 状态为 YES 的任务。
  2. 排序竞争:在这些已经就绪的任务中,队列会参考 queuePriority 来决定启动顺序。
  3. 非绝对执行:它不能保证优先级高的任务一定比优先级低的任务先完成,甚至不能百分之百保证先启动

为什么是“软”的?

  • 依赖关系高于优先级:如果一个高优先级任务依赖于一个低优先级任务,那么低优先级任务必须先执行。此时优先级失效。
  • 并发数限制:如果 maxConcurrentOperationCount 大于 1,系统可能会同时启动高低优先级的任务。

2. queuePriority 与 QoS (Quality of Service) 的区别

这是最容易混淆的概念。简单来说:queuePriority 决定“先后”,而 QoS 决定“快慢”。

特性queuePriority (队列优先级)Quality of Service (QoS)
作用范围仅在 同一个队列 内部有效。全局系统 范围内有效。
控制对象控制任务在队列中的入场顺序控制线程的硬件资源分配(CPU、磁盘、网络)。
影响维度调度顺序。CPU 周期、线程优先级、IO 优先级。
典型值VeryLow, Normal, High 等。UserInteractive, Utility, Background 等。

形象比喻:

  • queuePriority:就像在银行排队,你是 VIP 客户,可以排在普通客户前面(优先进窗口)。
  • QoS:就像你进了窗口后,银行给你的办事效率。你是高 QoS,柜员就全力以赴帮你办;你是低 QoS,柜员可能一边喝咖啡一边慢悠悠地处理。

3. 优先级是如何影响调度的?

OperationQueue 内部维护着一个等待执行的池子

  1. 入队:任务进入池子,标记为 Pending
  2. 检查依赖:一旦任务的依赖项全部完成,该任务被标记为 Ready
  3. 排序触发:当线程池有空闲时,调度器扫描所有 Ready 任务。它会挑选 queuePriority 最高的那个交给 GCD 的底层线程池。
  4. 动态性:如果在执行过程中,有一个更高优先级的任务突然变为 Ready,且此时还有并发名额,它会立即被启动,而不会等待正在运行的低优先级任务结束。

4. 优先级反转 (Priority Inversion)

这是使用优先级时需要警惕的风险:如果一个 High 优先级的任务依赖于一个 Low 优先级的任务,而队列中又有大量的 Normal 任务。

  • 结果Low 任务因为优先级太低,一直抢不到资源执行,导致 High 任务被无限期阻塞。
  • 系统的应对:现代 iOS 系统会自动进行 “优先级提升” ,暂时提高那个被依赖的 Low 任务的优先级,确保整条链条能跑通。

总结:使用建议

  • 不要过度依赖优先级:复杂逻辑应通过 addDependency: 解决。
  • 优先设置 QoS:如果你想让某个后台任务不耗电、不发热,设置 qualityOfService = .background 比调整 queuePriority 有效得多。
  • UI 相关设为高:只有那些直接影响用户体验的操作(如加载当前屏幕的图片)才建议设为 .high