GCD与队列
来源:互联网 发布:越知月光图片 编辑:程序博客网 时间:2024/05/17 23:41
/**
开多条线程,不顺序执行!
全局队列本身就是一个并发队列
问题:
一. 全局队列 & 并发队列的区别
1. 全局队列只需要 get
* 没有 name
2. 并发队列需要 create
* 如果在 MRC 开发,需要自己 release
- dispatch_release(q);
* 有 name
- 关于名称,和 NSThread 的 name 属性类似
关于队列的选择
- 建议:前期日常开发中,建议选择 全局队列!
- 自己创建的并发队列,通常在开发第三方框架的时候会使用!
二. 全局队列 & 串行队列的选择
- 全局队列
* 调度任务的时候,多个线程,而且是顺序不固定
* 并发能力好
* 效率高,速度快,费电,费钱
- 串行队列(斯坦福大学)
* 调度任务,只有一条线程,顺序执行每一个任务
* 并发能力差
* 效率差,速度慢,省电,省钱
* 用户并不是什么时候都会希望快的!
选择依据:
- 如果是 WIFI 情况,使用全局队列,开启线程的数量 6 条左右
- 如果是 3G/4G,使用串行队列,如果使用全局队列,开启线程的数量控制在 2~3 条
*/
- (void)gcdDemo10 {
// 全局队列,是 gcd 为了方便程序员的多线程开发提供的 dispatch_get_global_queue
// 本身就是一个并发队列
/**
参数:
关于服务质量:苹果官方有一个视频 XPC 框架(用在 MAC 上开发的一个框架)和 GCD 的一个提升
1. iOS 8.0 告诉队列执行任务的"服务质量quality of service"
QOS_CLASS_USER_INTERACTIVE 0x21, 用户交互(希望尽快完成,用户对结果很期望,不要放太耗时操作)
QOS_CLASS_USER_INITIATED 0x19, 用户期望(不要放太耗时操作)
QOS_CLASS_DEFAULT 0x15, 默认(不是给程序员使用的,用来重置对列使用的)
QOS_CLASS_UTILITY 0x11, 实用工具(耗时操作,可以使用这个选项)
QOS_CLASS_BACKGROUND 0x09, 后台
QOS_CLASS_UNSPECIFIED 0x00, 未指定
iOS 7.0 之前 优先级
DISPATCH_QUEUE_PRIORITY_HIGH 2 高优先级
DISPATCH_QUEUE_PRIORITY_DEFAULT 0 默认优先级
DISPATCH_QUEUE_PRIORITY_LOW (-2) 低优先级
DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN 后台优先级
提示:不要选择 BACKGROUND 的选项,苹果认为:BACKGROUND 表示用户不需要知道任务什么时候完成!
选择这个选项,速度慢的令人发指!不利于调试!
关于优先级,不要搞太负责,就用最简单的
结论:如果要做 iOS 8.0 & iOS 7.0 的适配:
dispatch_get_global_queue(0, 0);
提示:如果在今后,iOS 8.0 & 9.0 适配的时候,应该选择 QOS_CLASS_UTILITY
2. Flags that are reserved for future use
标记是为了未来使用保留的!这个参数应该永远指定为 0
*/
dispatch_queue_t q = dispatch_get_global_queue(0, 0);
// 2. 异步执行
for (int i = 0; i < 10; ++i) {
dispatch_async(q, ^{
NSLog(@"%@ %d", [NSThread currentThread], i);
});
}
NSLog(@"come here");
}
// MARK: - "主队列同步任务不死锁"(暂时不要求掌握)
- (void)gcdDemo9 {
// 1. 并发队列
dispatch_queue_t q = dispatch_queue_create("itheima", DISPATCH_QUEUE_CONCURRENT);
// 2. 任务
void (^task)() = ^ {
NSLog(@"%@", [NSThread currentThread]);
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"come here %@", [NSThread currentThread]);
});
NSLog(@"hahah %@", [NSThread currentThread]);
};
// 3. 异步执行任务
dispatch_async(q, task);
}
// MARK: - "同步"执行任务的作用
// 同步任务的增强演练(暂时不要求掌握)
/**
提示:通过 block 的嵌套,能够让任务非常的复杂!
复杂到,很难用一张表格来描述各种组合!
*** 需要理解队列&执行任务的函数的特点!
强烈建议:多线程的目的,是将耗时操作放在后台,不要把代码写的太复杂!
*/
- (void)gcdDemo8 {
// 1. 队列
dispatch_queue_t q = dispatch_queue_create("itheima", DISPATCH_QUEUE_CONCURRENT);
// 2. 任务
void (^task)() = ^ {
dispatch_sync(q, ^{
NSLog(@"Login %@", [NSThread currentThread]);
});
dispatch_async(q, ^{
NSLog(@"Download A %@", [NSThread currentThread]);
});
dispatch_async(q, ^{
NSLog(@"Download B %@", [NSThread currentThread]);
});
};
// 3. 异步执行 task
dispatch_async(q, task);
}
// 同步任务的基础演练!
- (void)gcdDemo7 {
// 例子:用户登录,下载A,下载B
// 要求:必须用户登录成功后,才允许下载
// 1. 队列
dispatch_queue_t q = dispatch_queue_create("itheima", DISPATCH_QUEUE_CONCURRENT);
// 2. 同步执行任务 - 作用可以让一些异步执行的任务 "依赖" 某一个特殊的任务(用户登录)
dispatch_sync(q, ^{
NSLog(@"Login %@", [NSThread currentThread]);
});
dispatch_async(q, ^{
NSLog(@"Download A %@", [NSThread currentThread]);
});
dispatch_async(q, ^{
NSLog(@"Download B %@", [NSThread currentThread]);
});
}
// MARK: - 主队列
/**
主队列 同步执行
提问:开线程吗?come here?
猜测:不开,最后!
结果:会造成死锁!
关于死锁:记住主队列的特点就容易理解!主线程有任务就暂时不调度任务!
*/
- (void)gcdDemo6 {
// 1. 队列
dispatch_queue_t q = dispatch_get_main_queue();
NSLog(@"!!!!");
// 2. 同步执行
dispatch_sync(q, ^{
NSLog(@"%@", [NSThread currentThread]);
});
NSLog(@"come here");
}
/**
主队列 "异步"执行 - 线程间通讯的!
主队列,专门负责在主线程上调度任务,所有的任务执行就应该在主线程上执行!
提问:开线程吗?come here?
猜测:不开? 最后/不确定!
答案:不开,最前面!
*/
- (void)gcdDemo5 {
// 1. 队列 - 程序一启动,主线程就已经存在,主队列也同时 就存在了,只需要获取不需要创建
dispatch_queue_t q = dispatch_get_main_queue();
// 2. 异步执行
for (int i = 0; i < 10; ++i) {
dispatch_async(q, ^{
NSLog(@"%@ - %d", [NSThread currentThread], i);
});
}
NSLog(@"睡会");
[NSThread sleepForTimeInterval:1.0];
NSLog(@"come here");
}
// MARK: - 并发队列
/**
并发队列,同步执行任务
和 串行队列"同步执行"任务结果是一样的
提问:开线程吗?开几条线程?come here?
猜测:不开!没有条!最后!
结果:全中!
*/
- (void)gcdDemo4 {
// 1. 队列
dispatch_queue_t q = dispatch_queue_create("itheima", DISPATCH_QUEUE_CONCURRENT);
// 2. 同步执行
for (int i = 0; i < 10; ++i) {
dispatch_sync(q, ^{
NSLog(@"%@ %d", [NSThread currentThread], i);
});
}
NSLog(@"come here");
}
/**
并发队列,可以同时调度多个任务
异步执行:可以开启线程
队列,本质上仍然是按照"先进先出"的方式来调度任务,而任务具体执行情况,是由 CPU 决定!
提问:开线程吗?开几条线程?come here?
猜测:开!N条!不确定!
答案:开线程,线程条数由GCD决定,不确定!
*/
- (void)gcdDemo3 {
// 1. 队列
dispatch_queue_t q = dispatch_queue_create("itheima", DISPATCH_QUEUE_CONCURRENT);
// 2. 异步执行
for (int i = 0; i < 10; ++i) {
dispatch_async(q, ^{
NSLog(@"%@ %d", [NSThread currentThread], i);
});
}
NSLog(@"come here");
}
// MARK: - 串行队列
// 串行队列 同步执行
/**
提问:开线程吗?开几条线程?come here?
猜测:不开!没有!最后!
答案:全中
原因:同步任务不会开启线程,当前代码不执行完,不会执行后续的代码
*/
- (void)gcdDemo2 {
// 1. 队列
dispatch_queue_t q = dispatch_queue_create("itheima", NULL);
// 2. 执行任务的函数
for (int i = 0; i < 10; ++i) {
// 10 个异步
dispatch_sync(q, ^{
NSLog(@"%@", [NSThread currentThread]);
});
NSLog(@"---- %d", i);
}
NSLog(@"come here");
}
// 串行队列 异步执行
/**
提问:开线程吗?开几条线程?come here?
猜测:开!不确定!不确定!
答案:开!开一条!不确定!
原因:串行队列,一个接一个的调度任务!
*/
- (void)gcdDemo1 {
// 1. 队列
/**
参数:
1. 队列的名称,类似于 NSThread 的 name 属性,是一个 C 语言的 字符串
2. 队列的属性
- DISPATCH_QUEUE_SERIAL(NULL) 串行队列
- DISPATCH_QUEUE_CONCURRENT 并发队列
使用 \ 拼接宏,使用宏即可
*/
// dispatch_queue_t q = dispatch_queue_create("itheima", DISPATCH_QUEUE_SERIAL);
// 这种写法更常见
dispatch_queue_t q = dispatch_queue_create("itheima", NULL);
// 2. 执行任务
for (int i = 0; i < 10; ++i) {
// 10 个异步
dispatch_async(q, ^{
NSLog(@"%@", [NSThread currentThread]);
});
}
NSLog(@"come here");
}
调度组
- (void)group2 {
// 1. 群组-统一监控一组任务
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t q = dispatch_get_global_queue(0, 0);
// 1> 入组 -> 之后的 block 会被 group 监听
// dispatch_group_enter 一定和 dispatch_group_leave 要配对出现
dispatch_group_enter(group);
dispatch_async(q, ^{
NSLog(@"task1 %@", [NSThread currentThread]);
// block 的末尾,所有任务执行完毕后,添加一个出组
dispatch_group_leave(group);
});
// 2> 再次入组
dispatch_group_enter(group);
dispatch_async(q, ^{
[NSThread sleepForTimeInterval:1.0];
NSLog(@"task2 %@", [NSThread currentThread]);
// block 的末尾,所有任务执行完毕后,添加一个出组
dispatch_group_leave(group);
});
// 3. 群组结束
// dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// NSLog(@"OVER");
// });
// 4. 群组等待 -> 等到永远,死等,等到所有任务完成
// 阻塞式的等待,群组任务不执行完,后续代码无法执行!
// (知道就行)
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
NSLog(@"come here");
}
// MARK: 调度组
// 应用场景:需要在所有异步任务执行完毕后,统一获得一个通知!
// 新浪微博提前将所有的缩略图(2k~3k)下载到本地,统一刷新表格,就可以针对不同的图片宽高设计UI
// 如果图片在服务器上,是无法直接获得宽高
- (void)group1 {
// 1. 群组-统一监控一组任务
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t q = dispatch_get_global_queue(0, 0);
// 2. 添加任务
// group 负责监控任务,queue 负责调度任务
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]);
});
// 3. 监听所有任务完成 - 等到 group 中的所有任务执行完毕后,"由队列调度 block 中的任务异步执行!"
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// 修改为主队列,后台批量下载,结束后,主线程统一更新UI
NSLog(@"OK %@", [NSThread currentThread]);
});
NSLog(@"come here");
}
- GCD队列与任务
- GCD与队列
- GCD中的队列与任务
- GCD之串行队列与并发队列
- GCD队列与线程的思考
- GCD全局队列与主队列
- GCD中的队列与任务组合对比
- GCD中任务与队列(一)
- GCD队列
- GCD队列
- GCD编程-串行队列与并发队列
- 多线程GCD初级讲解,队列与同步异步区别
- GCD串行队列
- GCD并发队列
- GCD 基础 (队列)
- GCD:创建并发队列
- GCD—队列组
- GCD各种队列
- JFinal学习笔记-Interceptor详解
- vim--字符串替换
- 实时网络游戏-网络延迟时客户端显示问题
- 设计模式从零到一之六大原则
- jenkins插件地址
- GCD与队列
- Weka 常用分类算法效果比较
- mpv for mac 修改外挂字幕乱码问题
- 创建 OVS vlan100 netwrok - 每天5分钟玩转 OpenStack(137)
- UART学习笔记二:如何去check数据帧
- 仿淘宝首页轮播
- Ubuntu启动出现GRUB rescue 错误的解决方法
- 正则基础之——捕获组(capture group)
- 占位