多线程之GCD(Grand Central Dispatch)
来源:互联网 发布:首届江苏网络 编辑:程序博客网 时间:2024/05/16 18:43
GCD是纯C语言,但又溶有面向对象思想、基于Block。
1、GCD优点:
- 易用:GCD比thread更简单易用,基于Block的特性导致它能极为简单的在不同代码作用域之间传递上下文。
- 效率:GCD在很多地方比之专门创建消耗资源的线程更实用、快速。
- 性能:GCD自动根据系统负载来增减线程数量,减少了上下文切换以及提高了计算效率。
2、GCD的使用
2.1.dispatch async异步操作
2.1.1.定义想要执行的操作(任务),追加到适当的队列中(Dispatch Queue)
2.12.Queue类型:
(1)Serial Dispatch Queue — 等待现在正在执行的任务处理结束(串行)
(2)Concurrent Dispatch Queue — 不等待现在正在执行的任务处理结束(并行、并发)
2.1.3.自己定义queue,把任务加到自定义的queue之中
(1)创建queue
//第一个参数:给队列起名字 //第二个参数:queue的类型 (默认是串行的) dispatch_queue_t queue1 = dispatch_queue_create("com.wxhl.gcd.Queue1", NULL); dispatch_queue_t queue2 = dispatch_queue_create("com.wxhl.gcd.Queue2", DISPATCH_QUEUE_CONCURRENT); //并行的queue
(2)创建要执行的任务,加到queue中执行
dispatch_async(queue2, ^{ for (int i = 0; i < 50; i ++) { NSLog(@"GCD : %d", i); } });
2.1.4.使用系统给提供的queue(推荐)
两种
Main Dispatch Queue Global Dispatch Queue
串行(主线程) 并行
//main dispatch_queue_t mainQueue = dispatch_get_main_queue(); dispatch_async(mainQueue, ^{ ; }); //global //参数一:优先级 //参数二:标识符 dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_async(globalQueue, ^{ //请求网络数据 //显示在UI界面上 dispatch_async(dispatch_get_main_queue(), ^{ //UI相关的代码 }); }); //主线程 for (int i = 0; i < 50; i ++) { NSLog(@"主线程 : %d", i); }
//async: asynchronous 将任务异步的追加到队列中 dispatch_async(dispatch_get_global_queue(0, 0), ^{ NSLog(@"async"); });
2.2 dispatch sync同步操作
//sync: synchronous 将任务同步的追加到队列中(等队列中的任务执行完,再将任务追加到队列) //是同步追加,不是任务同步执行,在串行队列中,任务才同步执行 dispatch_sync(dispatch_get_global_queue(0, 0), ^{ NSLog(@"sync"); }); **dispatch_sync的问题:容易产生死锁** 示例1: dispatch_sync(dispatch_get_main_queue(), ^{ NSLog(@"hello"); }); NSLog(@"主线程"); //上述代码在主队列中执行指定的block,等待其执行结束 //而主队列中本来就在执行上述代码,无法执行追加的block 示例2: //串行的队列 dispatch_queue_t queue = dispatch_queue_create("com.wxhl.GCD.queue", NULL); dispatch_async(queue, ^{ dispatch_sync(queue, ^{ NSLog(@"串行队列"); }); });
3. GCD高级用法
3.1 Dispatch After
一段时间之后,把要执行的任务追加到队列当中
- (void)viewDidLoad { [super viewDidLoad]; //创建时间 //相对的时间点 相对第一个参数多长时间之后 dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 3ull * NSEC_PER_SEC); //时间的单位 //NSEC_PER_SEC 秒 //NSEC_PER_MSEC 毫秒 //NSEC_PER_USEC 微秒 //dispatch_time_t 指定的时间 dispatch_after(time, dispatch_get_main_queue(), ^{ NSLog(@"after 3s"); }); //第二种用法 dispatch_after_f(dispatch_time(DISPATCH_TIME_NOW, 3ull * NSEC_PER_SEC), dispatch_get_main_queue(), NULL, func1); //自己使用 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5ull * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ ; });#warning 注意 //1.不是一段时间之后执行相应的任务 (而是把要执行的任务追加到队列当中) //2.主线程 runloop 1/60秒检测事件, 追加的时间范围 3s - (3 + 1/60)s}void func1(){}@end
3.2 Dispatch Group
dispatch_group_async :使用 group 监视 队列任务的执行
dispatch_group_notify:所有任务执行结束汇总,不阻塞当前线程
dispatch_group_wait: 等待直到所有任务执行结束,中途不能取消,阻塞当前线程
- (void)viewDidLoad { [super viewDidLoad]; //1.创建 group dispatch_group_t group = dispatch_group_create(); //2.获取队列 dispatch_queue_t queue = dispatch_get_global_queue(0, 0); //3.使用 group 监视 队列任务的执行 dispatch_group_async(group, queue, ^{ NSLog(@"task 1"); }); dispatch_group_async(group, queue, ^{ NSLog(@"task 2"); }); dispatch_group_async(group, queue, ^{ NSLog(@"task 3"); }); dispatch_group_async(group, queue, ^{ sleep(6); NSLog(@"task 4"); }); //(1)监视的函数 //监视到队列里任务执行结束,执行block里面的任务 dispatch_group_notify(group, queue, ^{ //结束处理 NSLog(@"done"); }); //(2) //等待time时间,根据wait函数的返回值确定队列中任务是否执行结束,5秒后汇总结果,不管任务有没有执行完 dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC); //dispatch_group_wait 指定的时间之后 看一眼queue的任务是否执行完毕 //如果执行完,返回0 //如果没有执行完,返回非0值 long result = dispatch_group_wait(group, time); if (result == 0) { NSLog(@"finish"); } else { NSLog(@"not finish"); } //dispatch_group_wait 会堵塞当前线程 一直在调用这个函数 等待指定的时间之后才会返回 sleep(2); NSLog(@"main");}@end
3.3 dispatch once实现单例
ViewController.m
- (void)viewDidLoad { [super viewDidLoad]; //dispatch once //保证block里的任务只执行一次 static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ NSLog(@"只会执行一次"); }); }@end
AddressBook.m
#import "AddressBook.h"static AddressBook *instance = nil;@implementation AddressBook/* * 单例 单例模式 尽量不要使用 * 1.含义:一个类只创建一个对象 * 2.生命周期:从创建开始,应用程序退出结束 * 3.取得单例对象的方法,命名规则: share default * 4.内存管理尽量由该类来管理 */+ (AddressBook *)sharedInstance{ //onceToken 标记block里的代码是否执行过 static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ instance = [[AddressBook alloc] init]; }); return instance;}//alloc 会自动调用 allocWithZone://zone 空间 分配内存空间(zone),创建对象+ (id)allocWithZone:(NSZone *)zone{ if (instance == nil) { instance = [super allocWithZone:zone]; } return instance;}@end
4. 小结:
- 安全:无需加锁或其他同步机制。
- 充分利用多核
- 所有多线程代码集中在一起,便于维护
- GCD中无需实用@autoreleasepool
- 如果要顺序执行,可以使用dispatch_sync同步方法(dispatch_sync无法确定任务的执行顺序)
- 调用主线程队列任务更新UI时,最好使用同步方法
2 0
- 多线程之GCD(Grand Central Dispatch)
- ios多线程之GCD(Grand Central Dispatch)
- iOS多线程之Grand Central Dispatch 简称(GCD)
- IOS 多线程之GCD(Grand Central Dispatch)
- IOS多线程GCD(Grand central Dispatch)
- Grand Central Dispatch(GCD)
- Grand Central Dispatch(GCD)
- GCD(Grand Central Dispatch)
- Grand Central Dispatch(GCD)
- GCD(Grand central dispatch)
- Grand Central Dispatch(GCD)
- iOS多线程编程之Grand Central Dispatch(GCD)
- iOS多线程编程之Grand Central Dispatch(GCD)
- iOS多线程编程之Grand Central Dispatch(GCD)
- iOS 多线程编程之Grand Central Dispatch(GCD)
- iOS多线程编程之Grand Central Dispatch(GCD)
- iOS多线程开发系列之(三)Grand Central Dispatch(GCD)
- iOS多线程开发(五)---GCD(Grand Central Dispatch)
- U3D——刀光轨迹插件
- 开源协议许可证浅析
- 新装修的房子,美呆了吧
- springMVC上传文件
- android--使用Struts2服务端与android交互
- 多线程之GCD(Grand Central Dispatch)
- Map和Reduce处理过程分析
- C语言 使用结构体实现简单的通讯录
- js实现表格操作-排序
- Could not compile the mapping document: *******.hbm.xml 的解决方法
- solution for GRASS GIS 6.4.3 on linux failed to open the gui
- 蓝桥杯 水水搜索
- linux server的idle timeout情况整理(设置不好有可能会导致事故)
- 关于生成并发唯一性流水号的解决方案