iOS开发 GCD详解
2020-09-17 本文已影响0人
Hiker5
简书中已有博主写的很详细,这里做个记录,方便自己日后查阅。
参考:https://www.jianshu.com/p/2d57c72016c6
一、主要概念:
1.线程
GCD会自动管理线程的生命周期(创建线程、调度任务、销毁线程)。只要你正确使用GCD中的队列与任务,就不需要考虑线程的生命周期问题。
2.队列
串行队列:一个接一个的调度任务。Dispatch Queue Serial
// 串行队列的创建方法
dispatch_queue_t queue = dispatch_queue_create("net.bujige.testQueue", DISPATCH_QUEUE_SERIAL);
并发队列:可以同时调度多个任务。Dispatch Queue Concurrent
// 并发队列的创建方法
dispatch_queue_t queue = dispatch_queue_create("net.bujige.testQueue", DISPATCH_QUEUE_CONCURRENT);
主队列:全局串行队列,由主线程串行调度任务,并且只有一个。Main
可使用 dispatch_get_main_queue() 方法获得主队列。
全局队列:没有名称的并发队列。Global
// 全局并发队列的获取方法
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
3.任务
同步执行任务
// 同步执行任务创建方法
dispatch_sync(queue, ^{
// 这里放同步执行任务代码
});
异步执行任务
// 异步执行任务创建方法
dispatch_async(queue, ^{
// 这里放异步执行任务代码
});
4.队列组 dispatch_group,关键词有
dispatch_group_async
dispatch_group_notify
dispatch_group_enter
dispatch_group_leave
dispatch_group_wait
调用队列组的 dispatch_group_async 先把任务放到队列中,然后将队列放入队列组中。或者使用队列组的 dispatch_group_enter、dispatch_group_leave 组合来实现 dispatch_group_async。
例子
/**
* 队列组 dispatch_group_notify
*/
- (void)groupNotify {
NSLog(@"currentThread---%@",[NSThread currentThread]); // 打印当前线程
NSLog(@"group---begin");
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 追加任务 1
[NSThread sleepForTimeInterval:2]; // 模拟耗时操作
NSLog(@"1---%@",[NSThread currentThread]); // 打印当前线程
});
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 追加任务 2
[NSThread sleepForTimeInterval:2]; // 模拟耗时操作
NSLog(@"2---%@",[NSThread currentThread]); // 打印当前线程
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// 等前面的异步任务 1、任务 2 都执行完毕后,回到主线程执行下边任务
[NSThread sleepForTimeInterval:2]; // 模拟耗时操作
NSLog(@"3---%@",[NSThread currentThread]); // 打印当前线程
NSLog(@"group---end");
});
}
5.栅栏 : 将两组异步执行的操作组给分割起来。等第一组执行完再执行第二组。dispatch_barrier_async
/**
* 栅栏方法 dispatch_barrier_async
*/
- (void)barrier {
dispatch_queue_t queue = dispatch_queue_create("net.bujige.testQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
// 追加任务 1
[NSThread sleepForTimeInterval:2]; // 模拟耗时操作
NSLog(@"1---%@",[NSThread currentThread]); // 打印当前线程
});
dispatch_async(queue, ^{
// 追加任务 2
[NSThread sleepForTimeInterval:2]; // 模拟耗时操作
NSLog(@"2---%@",[NSThread currentThread]); // 打印当前线程
});
dispatch_barrier_async(queue, ^{
// 追加任务 barrier
[NSThread sleepForTimeInterval:2]; // 模拟耗时操作
NSLog(@"barrier---%@",[NSThread currentThread]);// 打印当前线程
});
dispatch_async(queue, ^{
// 追加任务 3
[NSThread sleepForTimeInterval:2]; // 模拟耗时操作
NSLog(@"3---%@",[NSThread currentThread]); // 打印当前线程
});
dispatch_async(queue, ^{
// 追加任务 4
[NSThread sleepForTimeInterval:2]; // 模拟耗时操作
NSLog(@"4---%@",[NSThread currentThread]); // 打印当前线程
});
}
6.信号量 : dispatch_semaphore
GCD 中的信号量是指 Dispatch Semaphore,是持有计数的信号。提供有三个方法
-
dispatch_semaphore_create
:创建一个Semaphore,并初始化信号总量
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);//一般为0,在线程安全是设置为1,看需求
-
dispatch_semaphore_signal
:发送一个信号,让信号量加1 -
dispatch_semaphore_wait
:可以使总信号量减 1,信号总量小于 0 时就会一直等待(会阻塞所在线程,所以一般是加在并发队列中,让其新建线程,就不会影响当前线程),等于0,就可以正常执行。
Dispatch Semaphore 在实际开发中主要用于:
- 保持线程同步,将异步执行任务转换为同步执行任务
- 保证线程安全,为线程加锁,利用
dispatch_semaphore_wait
等于0才执行否则阻塞所在线程的特性。(电影院两个窗口同时卖票的例子)