Ios GCD问题和线程过多

Ios GCD问题和线程过多,ios,multithreading,grand-central-dispatch,Ios,Multithreading,Grand Central Dispatch,我有一个图像加载器类,它提供了NSURL从web加载图像并执行完成块。代码实际上很简单 - (void)downloadImageWithURL:(NSString *)URLString completion:(BELoadImageCompletionBlock)completion { dispatch_async(_queue, ^{ // dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HI

我有一个图像加载器类,它提供了NSURL从web加载图像并执行完成块。代码实际上很简单

- (void)downloadImageWithURL:(NSString *)URLString completion:(BELoadImageCompletionBlock)completion
{
    dispatch_async(_queue, ^{
//    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
        UIImage *image = nil;
        NSURL *URL = [NSURL URLWithString:URLString];
        if (URL) {
            image = [UIImage imageWithData:[NSData dataWithContentsOfURL:URL]];
        }  
        dispatch_async(dispatch_get_main_queue(), ^{
            completion(image, URLString);
        });
    });
}

当我替换

dispatch_async(_queue, ^{
被评论掉了

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{

图像加载速度快得多,这是非常合乎逻辑的(以前图像一次加载一个,现在一堆图像同时加载)。我的问题是,我可能有50个图像,我调用downloadImageWithURL:completion:method对它们进行处理,当我使用全局队列而不是_-queue时,我的应用程序最终崩溃,我看到有85多个线程。问题是我连续50次调用dispatch\u get\u global\u queue(dispatch\u queue\u PRIORITY\u HIGH,0)会导致GCD创建太多线程吗?我认为gcd会处理所有的线程,并确保线程数量不会太多,但如果不是这样,我有没有办法影响线程数量?

您可以使用
NSOperationqueue
,它由
NSURLConnection
支持

它具有以下实例方法:

- (void)setMaxConcurrentOperationCount:(NSInteger)count
来自

并发队列(也称为全局调度队列的一种类型)并发执行一个或多个任务,但任务仍在中启动 它们添加到队列的顺序。当前 正在执行的任务在由管理的不同线程上运行 调度队列。在任何给定点执行的任务的确切数量 是可变的,取决于系统条件

串行队列(也称为专用调度队列)执行一个任务 按它们添加到队列中的顺序进行。这个 当前正在执行的任务在一个不同的线程上运行(可能会有所不同) 从一个任务到另一个任务),由调度队列管理

通过将所有块调度到高优先级并发调度队列

[NSData dataWithContentsOfURL:URL]
这是一个同步阻塞网络操作,看起来默认的GCD行为将是生成一个线程负载,以便尽快执行您的阻塞

您应该调度到
DISPATCH\u QUEUE\u PRIORITY\u BACKGROUND
。这些任务绝不是“高度优先”。任何图像处理都应该在有空闲时间并且主线程上没有任何事情发生时进行


如果您想更好地控制这些事情同时发生的次数,我建议您考虑使用
NSOperation
。您可以使用
NSBlockOperation
将块嵌入到操作中,然后将这些操作提交到您自己的
NSOperationQueue
NSOperationQueue
有一个
-(NSInteger)maxConcurrentOperationCount
作为一项附加的好处,如果需要,也可以在调度后取消操作。

当全局并发队列的现有GCD工作线程上的工作单元在内核中被阻塞很长时间时,内核会创建额外的线程(只要全局队列上还有更多的工作等待完成)

这是必要的,以使应用程序能够继续取得总体进展(例如,执行一个挂起的块可能会使被阻止的线程解锁)

如果内核中阻塞工作线程的原因是IO(例如本例中的
+[NSData dataWithContentsOfURL:
),那么最好的解决方案是用一个API替换这些调用,该API将异步执行IO而不阻塞,例如用于联网的
NSURLConnection
,或用于文件系统IO的分派I/O

或者,您可以手动限制并发阻塞操作的数量,例如通过使用计数调度信号量


GCD会话详细讨论了这个主题。

不,这与队列优先级无关。GCD只在内核中的全局并发队列块的现有线程上阻塞相当长的时间后创建额外线程。@das谢谢我做了一些编辑,但请随时改进我的回答:)