Поскольку ваше устройство имеет только один процессор, GCD, вероятно, создает только один поток для выполнения блоков, и ваши блоки выполняются последовательно.Вы создали 10 различных потоков, и каждый из них получает небольшую часть доступного времени обработки.К счастью, сон не сильно нагружает процессор, поэтому все ваши потоки работают довольно хорошо.Попробуйте аналогичный тест на машине с 4 или 8 процессорными ядрами, и вы увидите, что GCD запускает больше ваших блоков параллельно.
Хорошая особенность GCD не в том, что она обязательно обеспечивает лучшую производительность, чем потоки.Дело в том, что программисту не нужно думать о создании потоков или сопоставлении количества потоков с количеством доступных процессоров.Вы можете создавать множество небольших задач, которые будут выполняться по мере доступности процессора, и позволить системе планировать эти задачи для вас.
Редактировать: Я немного поиграл с вашим кодом в простомпрограмма командной строки на моем Mac.Как я предложил в своем комментарии ниже, а также упомянул в ответе @ Ren-D, использование dispatch_async()
вместо dispatch_apply()
имеет большое значение.Вот код, который я использовал:
- (void)doIt:(NSNumber *)i
{
for (int j = 0; j < MAX_COUNT; j++)
;
NSLog(@"Thread#%i", [i intValue]);
}
- (void)doWork:(id)sender
{
for (int i = 0; i<10; i++) {
NSNumber *t = [NSNumber numberWithInt:i];
[NSThread detachNewThreadSelector:@selector(doIt:) toTarget:self withObject:t];
}
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
for (size_t i = 0; i<10; i++) {
dispatch_async(queue, ^(void) {
for (int j = 0; j < MAX_COUNT; j++)
;
NSLog(@"GCD#%u",(int)i);
});
}
NSLog(@"Done.");
sleep(15);
}
Как видите, я заменил ваши sleep()
вызовы на циклы for
, которые тратят некоторое время на подсчет.(Я запустил код на MacBook Pro - вы можете изменить значение MAX_COUNT
вниз, если вы работаете на iPhone.) Если вы используете sleep()
как в потоках, так и в блоке, то dispatch_async()
заставляет блоки вести себя так же, как потоки - все блоки работают одновременно и завершаются примерно в одно и то же время.Переключение на подсчет изменяет это поведение - все потоки работают одновременно, но блоки выполняются группами (на моей машине два процессора, поэтому блоки запускались группами по два).Это именно то, что вы ожидаете;Задача GCD состоит в том, чтобы ставить задачи в очередь и завершать их как можно быстрее, максимально используя имеющиеся ресурсы, а не запускать как можно больше задач одновременно.
Вот вывод из кода выше:
2011-04-14 02:48:46.840 BlockTest[14969:903] Hello, World!
2011-04-14 02:48:47.104 BlockTest[14969:903] Done.
2011-04-14 02:48:52.834 BlockTest[14969:1503] Thread#0
2011-04-14 02:48:52.941 BlockTest[14969:4f03] GCD#0
2011-04-14 02:48:52.952 BlockTest[14969:5003] GCD#1
2011-04-14 02:48:52.956 BlockTest[14969:4703] Thread#8
2011-04-14 02:48:53.030 BlockTest[14969:3703] Thread#4
2011-04-14 02:48:53.074 BlockTest[14969:2b03] Thread#1
2011-04-14 02:48:53.056 BlockTest[14969:4b03] Thread#9
2011-04-14 02:48:53.065 BlockTest[14969:3b03] Thread#5
2011-04-14 02:48:53.114 BlockTest[14969:3303] Thread#3
2011-04-14 02:48:53.138 BlockTest[14969:4303] Thread#7
2011-04-14 02:48:53.147 BlockTest[14969:3f03] Thread#6
2011-04-14 02:48:53.156 BlockTest[14969:2f03] Thread#2
2011-04-14 02:48:53.909 BlockTest[14969:4f03] GCD#2
2011-04-14 02:48:53.915 BlockTest[14969:5003] GCD#3
2011-04-14 02:48:54.700 BlockTest[14969:4f03] GCD#4
2011-04-14 02:48:54.721 BlockTest[14969:5003] GCD#5
2011-04-14 02:48:55.508 BlockTest[14969:4f03] GCD#6
2011-04-14 02:48:55.550 BlockTest[14969:5003] GCD#7
2011-04-14 02:48:56.321 BlockTest[14969:4f03] GCD#8
2011-04-14 02:48:56.345 BlockTest[14969:5003] GCD#9
Обратите внимание, что два блока фактически закончились раньше всех, кроме одного из потоков.Также: sleep(15)
в конце кода как раз для того, чтобы потоки и блоки могли записывать свои сообщения до завершения программы.В зависимости от того, в какую программу вы вставляете код, он может вам не понадобиться.