我在 GCD 的文档或教程中没有找到一个非常简单的问题:如果我将工作提交到队列的速度快于处理和删除的速度,会发生什么?我知道 GCD 队列没有大小限制,是否会一直堆积到程序内存不足为止?有什么办法可以妥善处理这种情况吗?
最佳答案
What happens if I'm submitting work to queues faster than it's being processed and removed?
这取决于。
如果将任务分派(dispatch)到单个/共享串行队列,它们只会被添加到队列中,并且将以 FIFO 方式处理它们。没问题。内存是你唯一的限制。
但是,如果将任务分派(dispatch)到并发队列,最终会出现“线程爆炸”,并且您将很快耗尽可用于该服务质量 (QoS) 的有限数量的工作线程。如果操作系统需要利用相同 QoS 的队列,这可能会导致不可预测的行为。因此,您必须非常小心,以避免这种线程爆炸。
参见 WWDC 2015 关于线程爆炸的讨论 Building Responsive and Efficient Apps with GCD并再次在 WWDC 2016 Concurrent Programming With GCD in Swift 3 .
Is there any way to properly handle this situation?
很难抽象地回答这个问题。不同的情况需要不同的解决方案。
对于线程爆炸的情况,解决方案是使用concurrentPerform
来约束并发程度(将并发限制为设备上的核心数量)。或者我们使用操作队列及其 maxConcurrentOperationCount 来将并发程度限制在合理的范围内。还有其他模式,但其想法是将并发限制为适合相关设备的并发。
但是,如果您只是将大量任务分派(dispatch)到串行队列,那么您无能为力(除了寻找并行机会,以有效利用所有 CPU 核心)。但这没关系,因为这就是队列的全部目的,让它按照提交的顺序执行任务,即使队列无法跟上。如果它不遵循这种 FIFO 类型的模式,它就不会是一个“队列”。
现在,如果处理无法足够快地处理的实时数据,则会遇到不同的问题。在这种情况下,您可能希望将输入的捕获与处理分离,并决定如何处理它。例如。例如,如果您无法跟上视频的实时处理,您还有一个选择。要么开始丢帧,要么异步/稍后处理数据。您只需决定什么最适合您的用例。我们无法抽象地回答这个问题。
关于ios - 大中央调度 : What happens when queues get overloaded?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63569923/