GCD创建的线程数?

时间:2011-08-27 10:05:38

标签: ios grand-central-dispatch

GCD创建了多少个线程是否有任何好的文档? 在WWDC,他们告诉我们它是围绕CPU核心建模的。但是,如果我称这个例子:

for (int i=1; i<30000; i++) {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [NSThread sleepForTimeInterval:100000];
    });
}
它打开66个线程,即使在iPad1上也是如此。 (当本地调用Lion时,它还打开66个线程)。为什么66?

3 个答案:

答案 0 :(得分:29)

首先,66 == 64(最大GCD线程池大小)+主线程+其他一些随机非GCD线程。

其次,GCD并不神奇。它经过优化,可以使CPU忙于主要受CPU限制的代码。 GCD的“神奇之处”在于,当工作项无意中并且短暂地等待操作完成时,它会动态地创建比CPU更多的线程。

话虽如此,代码可以通过故意睡眠或等待事件而不是使用调度源等待事件来混淆GCD调度程序。在这些场景中,工作块正在有效地实现自己的调度程序,因此GCD必须假定该线程已从线程池中选择。

简而言之,如果您的代码更喜欢dispatch_after()而不是“sleep()”(如API),并通过手工制作的事件循环(Unix select()/ poll(),Cocoa runloops或POSIX调度源),则线程池将以最佳方式运行条件变量)。

答案 1 :(得分:2)

文档避免提及创建的线程数。主要是因为最佳线程数在很大程度上取决于上下文。

Grand Cendral Dispatch的一个问题是,如果正在运行的任务阻塞,它将生成一个新线程。也就是说,在使用GCD时应该避免阻塞,因为线程数比核心数更多是不理想的。

在您的情况下,GCD检测到该任务处于非活动状态,并为下一个任务生成一个新线程。

为什么66这个限制超出了我的范围。

答案 2 :(得分:0)

繁忙线程的数量等于CPU内核。阻塞线程(您用sleepForTimeInterval阻塞的线程)不计算在内。

如果您将代码更改为此(快速):

for _ in 1..<30000 {
    DispatchQueue.global().async {
        while true {}
     }
}

您会看到(在iPhone SE上)仅创建了2个线程:

enter image description here

有一个限制,如果您遇到阻塞线程的问题(通常是由于死锁),则不会因为消耗大量内存而杀死您的应用。

从不阻塞线程,您将拥有与内核一样多的线程。