GCD
概念: 将任务添加到队列中, 并且指定执行任务的函数;
- 任务使用block封装, 没有参数, 没有返回值
- 执行任务的函数:
同步 dispatch_sync :
必须等待当前语句执行完毕,才会执行下一条语句;
不会开启线程;
在当前的block执行任务.
异步 dispathc_asyc:
不必等待当前语句执行完毕, 就可以一执行下一条语句;
会开启线程执行block中的任务;
异步是对线程的代名词. - 队列-负责调度任务:
串行队列: dispatch_queue_create("jianshu", NULL);
一次只能调度一个任务
并发队列: dispatch_queue_create("itheima", DISPATCH_QUEUE_CONCURRENT);
一次可以调度对个任务
主队列: dispatch_get_main_queue();
专门在主线程调度任务的队列
不会开启线程
在主线程空闲的时候才会调度任务在主线程执行
总结:
- 开不开线程是由执行任务的函数决定的:
同步不开线程;
异步开线程. - 开几条线程是由队列决定的:
串行队列开一条;
并发队列开多条线程, 具体数量由底层线程池决定;
全局队列:
是系统为了方便程序员开发提供的, 与并发队列效果一直, 但也有区别:
- 全局队列: 没有名称, 无论MRC或者ARC都不需要考虑释放, 日常开发建议使用全局队列.
- 并发队列:
- 有名称, 和NSThread的name属性类似;
- 如果在 MRC 开发时,需要使用 dispatch_release(q); 释放相应的对象
- dispatch_barrier 必须使用自定义的并发队列
- 开发第三方框架时,建议使用并发队列
延迟操作:
dispatch_after(dispatch_time_t when, dispatch_queue_t _Nonnull queue, ^(void)block)
- (void)delay {
/**
从现在开始,经过多少纳秒,由"队列"调度异步执行 block 中的代码
参数
1. when 从现在开始,经过多少纳秒
2. queue 队列
3. block 异步执行的任务
*/
dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC));
void (^task)() = ^ {
NSLog(@"%@", [NSThread currentThread]);
};
// 主队列
// dispatch_after(when, dispatch_get_main_queue(), task);
// 全局队列
// dispatch_after(when, dispatch_get_global_queue(0, 0), task);
// 串行队列
dispatch_after(when, dispatch_queue_create("itheima", NULL), task);
NSLog(@"come here");
}
一次执行:
有的时候,在程序开发中,有些代码只想从程序启动就只执行一次,典型的应用场景就是“单例”
- (void)once{
NSLog(@"来了");
//苹果提供的一次执行机制, 不仅执行一次, 而且线程安全
static dispatch_once_t onceToken;
NSLog(@"%ld",onceToken);
//苹果推荐使用GCD 一次执行, 效率高, 不要使用互斥锁, 效率低
dispatch_once(&onceToken, ^{
NSLog(@"执行了%@", [NSThread currentThread]);
});
}
- (void)testOnce
{
for (int i = 0; i< 10; i++) {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[self once];
});
}
}
调度组:
常规使用:
- (void)group1 {
// 1. 调度组
dispatch_group_t group = dispatch_group_create();
// 2. 队列
dispatch_queue_t q = dispatch_get_global_queue(0, 0);
// 3. 将任务添加到队列和调度组
dispatch_group_async(group, q, ^{
[NSThread sleepForTimeInterval:1.0];
NSLog(@"任务 1 %@", [NSThread currentThread]);
});
dispatch_group_async(group, q, ^{
NSLog(@"任务 2 %@", [NSThread currentThread]);
});
dispatch_group_async(group, q, ^{
NSLog(@"任务 3 %@", [NSThread currentThread]);
});
// 4. 监听所有任务完成
dispatch_group_notify(group, q, ^{
NSLog(@"OVER %@", [NSThread currentThread]);
});
// 5. 判断异步
NSLog(@"come here");
}
另一种写法:
// MARK: - 调度组 2
- (void)group2 {
// 1. 调度组
dispatch_group_t group = dispatch_group_create();
// 2. 队列
dispatch_queue_t q = dispatch_get_global_queue(0, 0);
// dispatch_group_enter & dispatch_group_leave 必须成对出现
dispatch_group_enter(group);
dispatch_group_async(group, q, ^{
NSLog(@"任务 1 %@", [NSThread currentThread]);
// dispatch_group_leave 必须是 block 的最后一句
dispatch_group_leave(group);
});
dispatch_group_enter(group);
dispatch_group_async(group, q, ^{
NSLog(@"任务 2 %@", [NSThread currentThread]);
// dispatch_group_leave 必须是 block 的最后一句
dispatch_group_leave(group);
});
// 4. 阻塞式等待调度组中所有任务执行完毕
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
// 5. 判断异步
NSLog(@"OVER %@", [NSThread currentThread]);
}
网友评论