GCD说明
开发者要做的只是定义想执行的任务并追加到适当的Dispatch Queue中。
Dispatch Queue
Dispatch Queue的官方定义:
A dispatch queue is an object-like structure that manages the tasks you submit to it.
Dispatch Queue按照追加的顺序执行处理。
Dispatch Queue有三种类型:
Type | Description |
---|---|
Serial Dispatch Queue | 使用一个线程按顺序一次执行一个任务,等待现在执行中的处理结束后再执行下一个 |
Concurrent Dispatch Queue | 使用多个线程,同时并行地执行一个或多个任务 |
Main Dispatch Queue | 全局可获得的Serial Queue,在应用的主线程中执行任务 |
dispatch_queue_create
要想得到Dispatch Queue,第一种方法是通过以下函数:
dispatch_queue_t mySearialDispatchQueue = dispatch_queue_create("com.example.gcd.MySerialDispatchQueue", NULL);`
dispatch_queue_create
函数的参数:
- 第一个参数指定Dispatch Queue的名称
- 第二个参数为NULL时,生成Serial Dispatch Queue;为DISPATCH_QUEUE_CONCURRENT时,生成Concurrent Dispatch Queue.
Main Dispatch Queue/Global Dispatch Queue
得到Dispatch Queue,第一种方法是通过获取系统标准提供的Dispatch Queue。
- Main Dispatch Queue:在主线程中执行的Dispatch Queue。为Serial Dispatch Queue
- 获取方法:
dispatch_queue_t mainDispatchQueue = dispatch_get_main_queue();
- 获取方法:
- Global Dispatch Queue:这是一个所有应用程序都能使用的Concurrent Dispatch Queue,没必要通过dispatch_queue_create函数生成,获取Global Dispatch Queue使用即可。
- 获取方法:
dispatch_queue_t globalDispatchQueueHight = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0); //函数第一个参数指定Global Dispatch Queue优先级:高、默认、低、后台等, //第二个参数为了以后拓展用,目前总是为0
- 获取方法:
dispatch_set_target_queue
变更生成的DIspatch Queue的执行优先级。
dispatch_after
想在指定时间后执行处理的情况,可使用dispatch_after函数来实现。
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 3ULL * NSEC_PER_SEC);
dispatch_after(time, dispatch_get_main_queue(), ^{ /*要执行的任务*/} );
Dispatch Group
在追加到Dispatch Queue中的多个处理全部结束后想执行结束处理,这种情况会经常出现。例如,追加3个Block到Global Dispatch Queue,这些Block如果全部执行完毕,就会执行Main Dispatch Queue中结束处理用的Block。
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(@"blk0");});
dispatch_group_async(group, queue, ^{NSLog(@"blk1");});
dispatch_group_async(group, queue, ^{NSLog(@"blk2");});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{NSLog(@"done");});
//也可以使用dispatch_group_wait(group, DISPATCH_TIME_FOREVER);//等待全部处理执行结束
dispatch_barrier_async
在访问数据库时会出现数据竞争:写入处理不可与其他的写入处理以及包含读取处理的其他某些处理并行执行。因为在dispatch_async函数中加入写入处理,那么根据Concurrent Dispatch Queue的性质,就有可能在追加到写入处理前面的处理中读取到与期待不符的数据,还可能因非法访问导致应用程序异常。因此使用dispatch_barrier_async
函数。dispatch_barrier_async
函数会等待追加到Concurrent Dispatch Queue上的并行执行的处理全部结束之后,再将指定的处理追加到该Concurrent Dispatch Queue上,然后由dispatch_barrier_async
函数追加的处理执行完毕后,Concurrent Dispatch Queue才恢复为一般的动作,追加到该Concurrent Dispatch Queue的处理又开始并行执行。示例如下:
dispatch_async(queue, blk0_for_reading);
dispatch_async(queue, blk1_for_reading);
dispatch_async(queue, blk2_for_reading);
dispatch_barrier_async(queue, blk_for_writing);
dispatch_async(queue, blk3_for_reading);
dispatch_async(queue, blk4_for_reading);
dispatch_async(queue, blk5_for_reading);
dispatch_apply
该函数按指定的次数将指定的Block追加到指定的Dispatch Queue中,并等待全部处理执行结束。
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");
//在Global Dispatch Queue中执行处理,各个处理的执行时间不定,但是输出结果中最后的done一定在最后的位置。这是因为dispatch_apply函数会等待全部处理执行结束。
dispatch_once
dispatch_once
函数保证在应用程序执行中只执行一次指定处理。实例如下
static dispatch_once_t pred;
dispatch_once (&pred, ^{/*初始化*/});
Dispatch I/O
读取大文件时,如果将文件分为合适的大小,一次使用多个线程更快的并列读取。能实现这一功能的就是Dispatch I/O和Dispatch Data。