Есть ли причина, по которой вы не используете GCD C API и семейство функций dispatch_*
? У вас нет большого контроля над GCD-аспектами NSOperationQueue
(например, в какую очередь вы хотите отправить блоки). Кроме того, я не могу сказать, используете ли вы iOS или нет, но NSOperationQueue
не не использует GCD на iOS. Это может быть причиной того, что он породил так много потоков. В любом случае ваш код будет короче и проще, если вы будете использовать GCD API напрямую:
- (double) detectCollisionsInArray:(NSArray*)objects
{
int count = [objects count];
if (count > 0)
{
double time = CFAbsoluteTimeGetCurrent();
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
for (int i = 0; i < count; i++)
{
dispatch_group_async(group, queue, ^{
for (int j = i + 1; j < count; j++)
{
dispatch_group_async(group, queue, ^{
/** LOTS AND LOTS OF WORK FOR EACH OBJECT **/
});
}
});
}
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
dispatch_release(group);
return CFAbsoluteTimeGetCurrent() - time;
}
return 0;
}
Вы можете использовать dispatch_group
, чтобы сгруппировать все исполнения вместе и подождать, пока все они завершатся с dispatch_group_wait
. Если вам не важно знать, когда заканчиваются блоки, вы можете игнорировать групповую часть и просто использовать dispatch_async
. Функция dispatch_get_global_queue
получит одну из 3 одновременных очередей (низкая, по умолчанию или с высоким приоритетом), в которую вы можете отправить свои блоки. Вам не нужно беспокоиться об ограничении числа потоков или чего-то подобного. Планировщик GCD должен сделать все это за вас. Просто убедитесь, что вы отправляете в параллельную очередь, которая может быть либо одной из 3 глобальных очередей, либо очередью, которую вы создали, передавая DISPATCH_QUEUE_CONCURRENT
в dispatch_queue_create
(это доступно начиная с OS X 10.7 и iOS 5.0).
Если вы выполняете какой-либо файловый ввод / вывод в каждом блоке или облагаете налогом какой-либо другой ресурс, вам, возможно, потребуется править в GCD и ограничить количество блоков, которые вы одновременно отправляете в очередь. Это будет иметь тот же эффект, что и ограничение числа одновременных операций в NSOperationQueue
. Для этого вы можете использовать семафор GCD:
- (double) detectCollisionsInArray:(NSArray*)objects
{
int count = [objects count];
if (count > 0)
{
double time = CFAbsoluteTimeGetCurrent();
dispatch_group_t group = dispatch_group_create();
dispatch_semaphore_t semaphore = dispatch_semaphore_create(10);
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
for (int i = 0; i < count; i++)
{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_group_async(group, queue, ^{
for (int j = i + 1; j < count; j++)
{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_group_async(group, queue, ^{
/** LOTS AND LOTS OF WORK FOR EACH OBJECT **/
dispatch_semaphore_signal(semaphore);
});
}
dispatch_semaphore_signal(semaphore);
});
}
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
dispatch_release(group);
dispatch_release(semaphore);
return CFAbsoluteTimeGetCurrent() - time;
}
return 0;
}
Как только вы освоитесь, GCD очень прост в использовании. Теперь я использую все это в своем коде.
Может кто-нибудь помочь поставить меня на правильный путь и, возможно, дать ссылку на хороший учебник по GCD?
Беги , не подходи к блогу Майка Эша . Его серия о GCD - самая ясная и краткая из всех, что я видел, и вам понадобится всего около 30 минут, чтобы прочитать все это. Видео Apple WWDC 2010 года на GCD И блоки тоже довольно хороши.