iOS GCD经常使用函数总结

GCD提供两种Dispatch Queue, 分别为Concurrent Dispatch Queue 和 Serial Dispatch Queue. 数据库

Serial Dispatch Queue 使用一个thread。 安全

Concurrent Dispatch Queue 使用多个thread。 多线程

获取Dispatch Queue: 并发

0)dispatch_queue_create app

dispatch_queue_t queue = dispatch_queue_create("name.of.your.queue",NULL);
第一个参数为queue的名字,第二个参数传NULL代表要建立一个Serial Dispatch Queue, 传入DISPATCH_QUEUE_CONCURRENT 建立一个 Concurrent Dispatch Queue。

若是是对数据库表更新或更新文件,最好为每个表或文件创建一个Serial Dispatch Queue,这样能保证只有一个thread会对数据进行更新。 async

若是对那些不会引发数据不一致问题的任务,须要放到Concurrent Dispatch Queue执行。 函数

1)从Main Dispatch Queue/Global Dispatch Queue获取 spa

//main queue
dispatch_queue_t mainQueue = dispatch_get_main_queue();

//global queue of high priority
dispatch_queue_t globalHigh = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,0);

//global queue of default priority
dispatch_queue_t globalDefault = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

//global queue of low priority
dispatch_queue_t globalLow = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW,0);

//global queue of background priority
dispatch_queue_t globalBackground = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND,0);
Main Dispatch Queue -> Serial dispatch queue

Global Dispatch Queue -> Concurrent dispatch queue 线程

dispatch_set_target_queue: 主要用来给新建的queue设置优先级 code

dispatch_queue_t serialQueue = dispatch_queue_create("name.of.queue",NULL);

dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND,0);

dispatch_set_target_queue(serialQueue, globalQueue);
须要注意的是,第一个参数是自定义的queue,而不是系统的queue。由于你不能给系统的queue设置权限。经过上面设置,serialQueue 就有了与globalQueue同样的优先级。其实这个函数不只能够设置queue的优先级,还能够设置queue之间的层级结构。


dispatch_after: 过一段时间执行queue中的task

dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 3ull * NSEC_PER_SEC);

dispatch_after(time, dispatch_get_main_queue(),^{
               NSLog(@"after 3 seconds...");});

Dispatch Group

0)dispatch_group_notify

dispatch group 能够在group中的dispatch queue都执行完以后,经过一个dispatch_group_notify通知回调。

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

dispatch_group_t group = dispatch_group_create();

dispatch_group_async(group, queue, ^{NSLog(@"task1");});
dispatch_group_async(group, queue, ^{NSLog(@"task2");});
dispatch_group_async(group, queue, ^{NSLog(@"task3");});

dispatch_group_notify(group, dispatch_get_main_queue(), ^{NSLog(@"finished...");});

输出总会保证"finished..."会在最后一句输出。

1)dispatch_group_wait

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

dispatch_group_t group = dispatch_group_create();

dispatch_group_async(group, queue, ^{NSLog(@"task1");});
dispatch_group_async(group, queue, ^{NSLog(@"task2");});
dispatch_group_async(group, queue, ^{NSLog(@"task3");});

dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

dispatch_group_wait提供了一种相似超时的机制,固然若是等待时间设置为DISPATCH_TIME_FOREVER,功能和dispatch_group_notify是同样的。

dispatch_barrier_async

dispatch_barrier_async是一个可让当前任务等待queue其余任务完成再执行的函数。例如,从数据库读取数据是能够多线程并发读取的,由于这样提升效率。可是,更新数据库数据,就要保证只有一个线程进行更新操做。因此,当更新操做发生的时候,必定要保证读操做和其余更新操做等待。

dispatch_queue_t queue = dispatch_queue_create("barrier.queue", DISPATCH_QUEUE_CONCURRENT);

dispatch_async(queue, read_block_0);
dispatch_async(queue, read_block_1);
dispatch_async(queue, read_block_2);
dispatch_async(queue, read_block_3);
dispatch_async(queue, read_block_4);

dispatch_barrier_async(queue, update_block);

dispatch_async(queue, read_block_5);
dispatch_async(queue, read_block_6);
dispatch_async(queue, read_block_7);
dispatch_async(queue, read_block_8);
dispatch_async(queue, read_block_9);
这样就能够保证只有当更新操做结束后,才会进行其余数据库读操做,保证了数据的一致性。


dispatch_apply

dispatch_apply用于给一个block添加到dispatch queue若干次。 “for”循环

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

dispatch_apply(10, queue, ^(size_t index) { NSLog(@"%zu",index);});

NSLog(@"done...");

dispatch_suspend/dispatch_resume

用于暂停和继续执行queue

dispatch semaphore

dispatch semaphore 适合处理比dispatch queue或者dispatch_barrier_async更小颗粒度的操做。

例如,

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

NSMutableArray *array = [[NSMutableArray alloc] init];

for (int i = 0; i < 100000; i++)
{
    dispatch_async(queue, ^{
      [array addObject:[NSNumber numberWithInt:i]];
    });
}

若是执行上段代码,由于NSMutableArray不是thread safe的,因此在global queue中对其进行添加对象,会致使程序crash掉。

使用dispatch semaphore咱们能够实现多线程对NSMutableArray进行操做

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);

NSMutableArray *array = [[NSMutableArray alloc] init];

for (int i = 0; i < 100000; i++)
{
    dispatch_async(queue, ^{

      dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

      [array addObject:[NSNumber numberWithInt:i]];

      dispatch_semaphore_signal(semaphore);
    });
}

dispatch semaphore 是一个信号量的counter,当counter为0,当前线程中止运行,当大于0,自减1,继续执行。

dispatch_semaphore_create

dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
初始化一个counter为1的semaphore.

dispatch_semaphore_wait

dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
等待counter大于0才运行,第二个参数为等待时间。执行后counter减1.

dispatch_semaphore_signal

dispatch_semaphore_signal(semaphore);
给counter加1

因此在上面的代码中,就能够保证在wait和signal中的[array addObject:[NSNumber numberWithInt:i]]; 就只有一个thread进行操做,保证了线程安全。

dispatch_onece

保证了dispatch_once中的代码只会被执行一次,经常使用于单例。

+ (id)sharedManager {
    static MyManager *sharedMyManager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedMyManager = [[self alloc] init];
    });
    return sharedMyManager;
}
相关文章
相关标签/搜索