2

我想将 GCD 用于一百个对象,这些对象都需要从服务器下载一些数据。如果我要遍历这些对象,并调用类似:

dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_async(q, ^{
    // Download data;
});

这些块会被智能排队并高效执行,还是我会遇到内存问题、性能问题,甚至是竞争条件?

我的两分钱是,顾名思义,块将排队,下载将一次开始一个,只要我在应用程序在所有下载完成之前终止时正确清理,就不应该有问题。

然而,另一个额外的问题:

如果我要创建 3-5 个队列并通过在队列之间分配下载来一次下载多个文件,我会受益更多吗?


实现了这个功能后,似乎接受的答案并不完整,或者我错过了重点。在全局队列(即并发队列)上调度块可能会导致问题,因为 GCD 可以调度的线程数是最大的(~64)。这仅适用于并发队列,因为它们需要为每个操作生成一个线程。但是,如果您创建自己的队列,则该队列将是一个顺序队列,一个接一个地执行块,即使在dispatch_async被调用时也是如此。这样,您可以确定您的队列只会产生 1 个线程,并将您的操作排队,并且永远不会遇到线程限制问题。

4

2 回答 2

4

解决您的第一个问题,即“这些块会智能排队并有效执行,还是我会遇到内存问题、性能问题,甚至是竞争条件”。

我的回答:

  1. 这些块是否会智能排队并有效执行:是的,毫无疑问它们会。

  2. 我是否会遇到内存问题,性能问题:这取决于情况。由于您正在调用异步方法,因此它不能保证第二次下载操作将在第一次下载操作完成后开始。如果您正在下载图像或视频,您可能会因为 CFDATA 或 CFDATA(store) 问题(可以处理)而遇到内存不足的问题。

  3. 甚至竞态条件:如果你知道如何以及何时切换线程,你永远不会陷入竞态条件。例如:如果您下载的类委托需要在主线程上调用,您将需要在主线程上启动连接,就像在 NSURLConnection 中一样。如果您在下载后处理 UI 元素,您仍然需要切换线程。否则不会发生竞争条件或死锁。

解决您的第二个问题“如果我要创建 3-5 个队列并通过在队列之间分配下载来随时下载多个文件,我会受益更多吗?”

如果我在你的位置,我会用一个队列来处理数百个对象。我一直处于这种情况,就我而言,我必须下载数千个文件。我会一次下载单个文件并进行清理,然后继续前进。好像您有数百个文件要下载,即使 0.1 MB 的额外分配也会给您带来性能问题。

于 2013-11-10T04:48:56.713 回答
0

来自 MacOS X 和 iOS (O'Reilly) 中的并发编程:

在此处输入图像描述

于 2016-11-05T07:32:40.800 回答