Grand Central Dispatch(GCD)是异步执行任务的技术之一,一般将应用程序中记述的线程管理用的代码在系统级实现。开发者值需要定义想执行的任务并追加到适当的Dispatch Queue中,GCD就生成必要的线程并计划执行任务。由于线程管理是作为系统的一部分来实现的,因此可以统一管理,也可以执行任务,这样就比以前用线程更有效率。
GCD使用举例
dispatch_async(queue,^{
/*
* 长时间处理任务(如AR图像识别,数据库访问等)
*/
dispatch_async(dispatch_get_main_queue(),^{
/*
* 只在主线程执行的任务,例如界面的更新
*/
});
});
GCD的API
Dispatch Queue
Dispatch Queue的种类 | 说明 |
---|---|
Serial Dispatch Queue | 串行线程 |
Concurrent Dispatch Queue | 并行线程 |
dispatch queue是线程执行处理的等待队列,应用程序通过dispatch_async
等API将执行的任务追加到Queue中。

一共存在两种Dispatch Queue 。
Dispatch Queue的种类 | 说明 |
---|---|
Serial Dispatch Queue | 串行线程 |
Concurrent Dispatch Queue | 并行线程 |


当队列为
serial
类型时,只有一个线程,并且任务按照串行执行。当队列为
concurrent
类型时,不止一个线程,任务是并发执行。
获取dispatch queue
使用dispathc_queue_create
创建
使用GCD的API生成dispatch queue。
dispatch_queue_t mySerialDispatchQueue = dispatch_queue_create("com.test.MySerialDispatchQueu",NULL);
第一个参数代表线程的名字,第二个参数NULL
代表使用serial dispatch queue
也就是串行的队列,如果要使用concurrent dispatch queue
需要传入DISPATCH_QUEUE_CONCURRENT
。
Serial Dispatch Queue
生成的数量应该仅限于必须要使用的串行线程数量,例如更行数据库时一个表生成一个。因为每生成一个Serial Dispatch Queue
系统就会生成一条线程,造成内存和时间的消耗。
当执行不发生数据竞争的问题的时,用Concurrent Dispatch Queue
。不管生成多少个Concurrent Dispatch Queue
,系统都能有效管理线程,不会出现Serial Dispatch Queue
的问题。
注意:使用
dispathc_queue_create
创建的线程使用结束后要进行释放
使用dispatch_release
释放:即Dispatch Queue 和 Objective-C的引用计数管理内存一样,需要使用dispatch_retain
和dispatch_release
进行内存管理
dispatch_queue_t queue = dispatch_create("com.test.MyConcurrentDispatchQueue",DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue,^{NSLog(@"block on queue")});
dispatch_release(queue);
Block
也会持有queue
所以不用担心在第三行之后,queue
对象销毁,只有当Block
也执行完了,才会进行回收内存。
使用系统提供的线程队列
不用特意生成线程,系统也会提供几个线程供使用
- Main Dispatch Queue:主线程,只用一个
- Global Dispatch Queue:供所有程序使用的
concurrent dispatch queue
,另外这些线程有四个优先级
名称 | 种类 | 说明 |
---|---|---|
Main Dispatch Queue | Serial Dispatch Queue | 主线程执行 |
Global Dispatch Queue(High Priority) | Concurrent Dispatch queue | 优先级最高 |
Global Dispatch Queue(Default Priority) | Concurrent Dispatch queue | 默认 |
Global Dispatch Queue(Low Priority) | Concurrent Dispatch queue | 优先级低 |
Global Dispatch Queue(Background Priority) | Concurrent Dispatch queue | 后台执行 |
// main dispatch queue 获取
dispatch_queue_t mainDispatchQueue = dispatch_get_main_queue();
// global dispatch queue (High Priority) 获取
dispatch_queue_t globalDispatchQueueHigh = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,0);
使用系统提供的线程不需要自行进行内存管理。
更改使用dispatch_queue_create生成的queue的优先级
使用dispatch_queue_create
生成的queue的优先级和默认的Global Dispatch Queue相同,可以使用dispatch_set_target_queue
来改变优先级
Dispatch_after(做定时任务)
比如3秒后处理一个任务
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW,3ull*NSEC_PER_SEC);
dispatch_after(time,queue,^{
// 任务
});
注意,这里的3秒是3秒后加入任务,不是精确的3秒,任务开始的最短时间在3秒后,最长在3秒加一个时间片。
3ull
中的ull代表unsigned long long 无符号长整型。
dispatch_group
- 创建group
dispatch_group_t dispatch_group_create(void);
- 给任务设置group
void dispatch_group_async(dispatch_group_t group,dispatch_queue_t queue,dispatch_block_t block);
- group里的任务全部执行完后执行最后一个任务
dispatch_group_notify(group,dispatch_get_main_queue(),^{NSlog(@"done");});
- 等待group完成
long dispatch_group_wait(dispatch_group_t group,dispatch_time_t timeout);
dispatch_barrier_async
在访问数据库或者文件的使用,如上所述,可以使用串行队列来避免竞争。
而读取不会发生竞争可以用并行线程。
也就是说,为了高效率地进行访问,读取处理追加到Concurrent Dispatch Queue中,写入处理在任一个读取处理没有执行的状态下,追加到Serial Dispatch Queue中。
这种情况可以使用dispatch_barrier_async
来解决读取的问题。
dispatch_sync
dispatch_async是异步执行的。
dispatch_sync是同步执行的。
dispatch_suspend/dispatch_resume
挂起和恢复queue
信号量
- 创建
dispatch_semaphore_t
dispatch_semaphore_create(long value);
- 触发信号量
long dispatch_semaphore_signal(dispatch_samaphore_t dsema); //成功后 value++
- 等待信号量
long dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout); //成功后 value --
网友评论