Ответ 1
Поскольку ваше устройство имеет только один процессор, 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) в конце кода находится там, чтобы потоки и блоки регистрировали свои сообщения до завершения программы. В зависимости от того, какую программу вы вставляете в код, вам может и не понадобиться.