GCD慢慢整理
来源:互联网 发布:玛士达编程用软件 编辑:程序博客网 时间:2024/06/06 12:46
/** 凡是函数名中带有create\copy\new\retain等字眼, 都应该在不需要使用这个数据的时候进行release GCD的数据类型在ARC环境下不需要再做release CF(Core Foundation)的数据类型在ARC\MRC环境下都需要再做release */
1. 队列类型
串行队列:一次只能处理一个任务。(FIFO)一行代码执行完才能执行下一行代码。
并行队列:可以同时处理多个任务。
串行队列
// 第一个参数:队列名随便写,方便调试区别队列// 第二个参数:一般用NULL(也就是DISPATCH_QUEUE_SERIAL)/**#define DISPATCH_QUEUE_SERIAL #define DISPATCH_QUEUE_CONCURRENTDISPATCH_QUEUE_SERIAL串行队列,遵循先进先出原则DISPATCH_QUEUE_CONCURRENT这个比较特殊,创建的是自定义并行队列*/
dispatch_queue_t queue = dispatch_queue_create("队列名方便调试区别", NULL);
主队列(也是串行队列的一种)
// (添加到主队列中的任务,都会自动放到主线程中去执行。)// 主队列一般运行一些需要与主线程同步的一些短时任务。dispatch_queue_t queue = dispatch_get_main_queue();
并发队列(全局队列)
在不得以的情况下可以用dispatch_queue_create创建(串行队列有介绍),但一般我们都要用系统预定义的并行队列。
// 第一个参数是优先级:一般用DISPATCH_QUEUE_PRIORITY_DEFAULT/**#define DISPATCH_QUEUE_PRIORITY_HIGH 2#define DISPATCH_QUEUE_PRIORITY_DEFAULT 0#define DISPATCH_QUEUE_PRIORITY_LOW (-2)#define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN*/// 第二个参数留着将来可能有用,默认为0 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
获取当前队列
// 如果在队列执行任务中调用,返回执行此任务的队列;如果在主线程中调用,将返回主队列;如果在一般线程(非主线程线程非队列执行任务)中调用,返回全局队列。 dispatch_queue_t queue = dispatch_get_current_queue();
2. 线程同步与异步
同步是指:发送方发出数据后,等接收方发回响应以后才发下一个数据包的通讯方式。
异步是指:发送方发出数据后,不等接收方发回响应,接着发送下个数据包的通讯方式。
同步就是你叫我去吃饭,我听到了就和你去吃饭;如果没有听到,你就不停的叫,直到我告诉你听到了,才一起去吃饭。
异步就是你叫我,然后自己去吃饭,我得到消息后可能立即走,也可能等到下班才去吃饭。
所以,要我请你吃饭就用同步的方法,要请我吃饭就用异步的方法,这样你可以省钱。
举个例子 打电话时同步 发消息是异步
线程与队列组合6种(2 X 3 = 6)(李明杰老师的视频整理的)
dispatch_sync (同步,不具备开启线程的能力)
/** * sync -- 串行队列 * 会不会创建线程:不会 * 任务的执行方式:串行执行(一个任务执行完毕后再执行下一个任务) */- (void)syncSerialQueue{ // 创建一个串行队列 dispatch_queue_t queue = dispatch_queue_create("cn.heima.queue", NULL); // 将 任务 添加到 串行队列 中 同步 执行 dispatch_sync(queue, ^{ NSLog(@"-----下载图片1---%@", [NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"-----下载图片2---%@", [NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"-----下载图片3---%@", [NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"-----下载图片4---%@", [NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"-----下载图片5---%@", [NSThread currentThread]); });}
/** * sync -- 主队列(不能用---会卡死) */- (void)syncMainQueue{ NSLog(@"syncMainQueue----begin--"); // 1.主队列(添加到主队列中的任务,都会自动放到主线程中去执行) dispatch_queue_t queue = dispatch_get_main_queue(); // 2.添加 任务 到主队列中 异步 执行 dispatch_sync(queue, ^{ NSLog(@"-----下载图片1---%@", [NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"-----下载图片2---%@", [NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"-----下载图片3---%@", [NSThread currentThread]); }); NSLog(@"syncMainQueue----end--");}// 主队列任务队列:->syncMainQueue()->dispatch_sync(queue, ^{})// 但是实际上是应该执行dispatch_sync(queue, ^{}),陷入死循环
/** * sync -- 并发队列 * 会不会创建线程:不会 * 任务的执行方式:串行执行(一个任务执行完毕后再执行下一个任务) * 并发队列失去了并发的功能 */- (void)syncGlobalQueue{ // 获得全局的并发队列 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); // 将 任务 添加到 全局并发队列 中 同步 执行 dispatch_sync(queue, ^{ NSLog(@"-----下载图片1---%@", [NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"-----下载图片2---%@", [NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"-----下载图片3---%@", [NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"-----下载图片4---%@", [NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"-----下载图片5---%@", [NSThread currentThread]); });}
dispatch_async(异步,具备开启线程的能力)
/** * sync -- 并发队列 * 会不会创建线程:不会 * 任务的执行方式:串行执行(一个任务执行完毕后再执行下一个任务) * 并发队列失去了并发的功能 */- (void)syncGlobalQueue{ // 获得全局的并发队列 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); // 将 任务 添加到 全局并发队列 中 同步 执行 dispatch_sync(queue, ^{ NSLog(@"-----下载图片1---%@", [NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"-----下载图片2---%@", [NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"-----下载图片3---%@", [NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"-----下载图片4---%@", [NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"-----下载图片5---%@", [NSThread currentThread]); });}
/** * sync -- 并发队列 * 会不会创建线程:不会 * 任务的执行方式:串行执行(一个任务执行完毕后再执行下一个任务) * 并发队列失去了并发的功能 */- (void)syncGlobalQueue{ // 获得全局的并发队列 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); // 将 任务 添加到 全局并发队列 中 同步 执行 dispatch_sync(queue, ^{ NSLog(@"-----下载图片1---%@", [NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"-----下载图片2---%@", [NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"-----下载图片3---%@", [NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"-----下载图片4---%@", [NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"-----下载图片5---%@", [NSThread currentThread]); });}
/** * async -- 并发队列(最常用) * 会不会创建线程:会,一般同时开多条 * 任务的执行方式:并发执行 */- (void)asyncGlobalQueue{ // 获得全局的并发队列 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); // 将 任务 添加 全局队列 中去 异步 执行 dispatch_async(queue, ^{ NSLog(@"-----下载图片1---%@", [NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"-----下载图片2---%@", [NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"-----下载图片3---%@", [NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"-----下载图片4---%@", [NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"-----下载图片5---%@", [NSThread currentThread]); });}
3. 队列组(dispatch_group_async)
可以实现监听一组任务是否完成,完成后得到通知执行其他的操作。这个方法很有用,比如你执行三个下载任务,当三个任务都下载完成后你才通知界面说完成的了。
dispatch_group_t group = dispatch_group_create();dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_group_async(group, queue, ^{ [NSThread sleepForTimeInterval:1]; NSLog(@"group1"); }); dispatch_group_async(group, queue, ^{ [NSThread sleepForTimeInterval:2]; NSLog(@"group2"); }); dispatch_group_async(group, queue, ^{ [NSThread sleepForTimeInterval:3]; NSLog(@"group3"); }); dispatch_group_notify(group, dispatch_get_main_queue(), ^{ NSLog(@"update UI"); });
4. 其它使用
线程通信
// 一般异步并行下载图片,然后到主线程刷新界面 dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_queue_t mainQueue = dispatch_get_main_queue(); dispatch_async(globalQueue, ^{ NSLog(@"donwload---%@", [NSThread currentThread]); // 1.子线程下载图片 // 2.回到主线程设置图片 dispatch_async(mainQueue, ^{ NSLog(@"setting---%@ %@", [NSThread currentThread], image); }); });
单例实现
static NSObject *object = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ object = [[NSObject alloc] init]; });
延时实现
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ NSLog(@"[%s]%d", __func__, __LINE__); });
0 0
- GCD慢慢整理
- NSOperation慢慢整理
- NSInvocation慢慢整理
- git慢慢整理
- ios事件慢慢整理
- URLSession慢慢整理
- AFNetworking慢慢整理
- GCD整理
- 数论之路慢慢之GCD性质
- 常用接口整理(慢慢补充)
- 正则表达式(慢慢整理)
- IOS9新特性慢慢整理
- GCD学习整理
- 2.GCD多线程整理
- GCD 整理(二)
- 整理GCD用法
- GCD用法整理
- 位操作大全(慢慢翻译整理)
- 关于kafka producer 分区策略的思考
- apache commons fileupload 1.3.1(九)FileUploadBase部分
- JS逻辑运算符&&与||的妙用
- 【MFC】:MFC关于文件读写的代码及结构体的错误问题
- NSDate 一些常用方法(待补充)
- GCD慢慢整理
- android开源框架学习---EventBus---源码分析
- 文章标题
- IOS-线程异步操作GCD
- 一个简单的jsp+servlet实例,实现简单的登录
- 各种姿势玩转KVC
- play framework authentification
- Android 中Handler引起的内存泄露
- 指针数组,指针指向const成员函数