Grand Central Dispatch:队列超载时会发生什么?

Grand Central Dispatch: What happens when queues get overloaded?

我在 GCD 的文档或教程中没有找到的一个非常简单的问题:如果我将工作提交到队列的速度快于它被处理和删除的速度,会发生什么情况?我知道 GCD 队列没有大小限制,会一直工作直到程序内存不足吗?有什么办法可以妥善处理这种情况吗?

What happens if I'm submitting work to queues faster than it's being processed and removed?

视情况而定。

  • 如果将任务分派到single/shared串行队列,它们只会被添加到队列中,并以先进先出的方式处理它们。没问题。内存是您唯一的限制。

  • 但是,如果将任务分派到并发队列,最终会出现“线程爆炸”,并且您将很快耗尽可用于该 quality-of-service(QoS ).如果 OS 需要利用具有相同 QoS 的队列,这可能会导致不可预测的行为。因此,您必须非常小心,避免这种线程爆炸。

    查看关于线程爆炸的讨论 WWDC 2015 Building Responsive and Efficient Apps with GCD and again in WWDC 2016 Concurrent Programming With GCD in Swift 3

Is there any way to properly handle this situation?

很难抽象地回答这个问题。不同的情况需要不同的解决方案。

在线程爆炸的情况下,解决方案是使用concurrentPerform来限制并发度(将并发限制为您设备上的核心数)。或者我们使用操作队列及其 maxConcurrentOperationCount 将并发程度限制在合理的范围内。也有其他模式,但想法是将并发限制为适合相关设备的模式。

但是,如果您只是将大量任务分派到串行队列,那么您无能为力(除了寻找并行机会,以有效利用所有 CPU's核心)。但这没关系,因为这就是队列的全部目的,让它按照提交的顺序执行任务,即使队列跟不上也是如此。如果它不遵循这种 FIFO 模式,它就不会是一个“队列”。

现在,如果处理 real-time 无法足够快地处理的数据,您就会遇到不同的问题。在这种情况下,您可能希望将输入的捕获与处理分离,并决定如何处理它。例如。例如,如果您跟不上 real-time 视频处理,您可以选择。您要么开始丢帧,要么处理数据 asynchronously/later。您只需要决定什么适合您的用例。我们无法抽象地回答这个问题。