Многопоточность в iOS. Введение в GCD, часть 2

В прошлой статье мы познакомились с очередями выполнения задач и с некоторыми функциями, которые позволяют запускать задачи на выполнение. В этой статье мы рассмотрим еще несколько функций, которые запускают задачи на выполнение.

dispatch_once

Функция dispatch_once используется, когда конкретную задачу нужно выполнить только один раз за все время жизни приложения. Это может быть полезным, например, при инициализации синглтона, как это советовали тут. Такие конструкции, я думаю, вы видели не раз:
static BOOL isSomethingInited = NO;
if ( isSomethingInited )
{
    // инициализируем что-нибудь
    // и выставляем флаг
    isSomethingInited = YES;
}
С помощью GCD и функции dispatch_once этот код можно заменить вот таким:
static dispatch_once_t task;
dispatch_once(&task, ^{
    // код
});

dispatch_after

Вы можете использовать эту функцию, когда хотите отложить выполнение задачи на некоторое время. Рассмотрим пример:
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
    // код
});
Обратите внимание на то, что нет гарантий, что код запуститься сразу по истечении времени. Когда пройдет время, задача станет в очередь на выполнение, а начнет она выполняться или нет — зависит уже от нагруженности самой очереди. Но, обычно, задачи стартуют во время или с небольшой погрешностью.
Время, когда запускать задачу на выполнение представлено структурой dispatch_time_t, которая создается функцией dispatch_time. Она определяет сколько времени (второй аргумент), прошло от конкретного времени (первый аргумент). В данном случае мы используем текуще время DISPATCH_TIME_NOW и отсчитываем от него две секунды. Время отсчета задается в нано секундах. Если мы хотим использовать время в секундах, то нам нужно умножать количество секунд на NSEC_PER_SEC (наносекунд в секунде). Если мы хотим отсчитать милисикунды, можно использовать NSEC_PER_MSEC).

dispatch_apply

Эта функция используется для запуска задачи на выполнение несколько раз. Функция возвращает управление когда все запущенные задачы будут закончены.
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply(10, queue, ^(size_t index) {
   // блок выполнится 10 раз
   // в блок передается номер запуска
});
dispatch_apply распаралеливает выполнение задач. Например, если запустить вот такой код:
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply(10, queue, ^(size_t index) {
    NSLog(@"%@ , %zu",[NSDate date], index);
});
В консоли мы можем увидеть вот такое:
2012-06-13 19:08:31 +0000 , 0
2012-06-13 19:08:31 +0000 , 2
2012-06-13 19:08:31 +0000 , 3
2012-06-13 19:08:31 +0000 , 4
2012-06-13 19:08:31 +0000 , 5
2012-06-13 19:08:31 +0000 , 6
2012-06-13 19:08:31 +0000 , 7
2012-06-13 19:08:31 +0000 , 8
2012-06-13 19:08:31 +0000 , 9
2012-06-13 19:08:31 +0000 , 1
Это говорит о том, что задачи действительно распарателиваются.
На этом все. В следующих статьях мы рассмотрим методы управления очередями и механизм семафоров в GCD. Спасибо за внимание!