GCD使用
来源:互联网 发布:单页面网站源码 编辑:程序博客网 时间:2024/06/08 10:33
一、GCD是什么。
GCD 是 libdispatch 的市场名称,而 libdispatch 作为 Apple 的一个库,为并发代码在多核硬件(跑 iOS 或 OS X )上执行提供有力支持。
它具有以下优点:
1.GCD 能通过推迟昂贵计算任务并在后台运行它们来改善你的应用的响应性能。
2.GCD 提供一个易于使用的并发模型而不仅仅只是锁和线程,以帮助我们避开并发陷阱。
3.GCD 具有在常见模式(例如单例)上用更高性能的原语优化你的代码的潜在能力。
二、系统提供的用法
为了方便GCD的使用,苹果提供了一些方法方便我们将Block放在主线程或者后台线程或者延后执行。
//子线程执行
dispatch_async(dispatch_get_global_queue(0, 0), ^{
//something
});
//主线程执行
dispatch_sync(dispatch_get_main_queue(), ^{
//something
});
//一次性执行
static dispatch_once_t onceTaken;
dispatch_once(&onceTaken, ^{
//something
});
//延迟2S加载
double delayInSecond = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSecond * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^{
//something
});
三、应用---延时
(1)调用NSObject的方法[self performSelector:@selector(run) withObject:nil afterDelay:2.0];// 2秒后再调用self的run方法(2)使用GCD函数dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ // 2秒后执行这里的代码... // 默认在主线程执行,你也可以并发,在子线程执行});(3)使用NSTimer[NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(test) userInfo:nil repeats:NO];
应用---一次性执行
使用dispatch_once函数能保证某段代码在程序运行过程中只被执行1次
static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{ // 只执行1次的代码(这里面默认是线程安全的)});// 适合做资源的加载,但是和懒加载不同,它一旦加载,加载一次,别人就不能加载,整个程序哦,全局性
应用---快速迭代
使用dispatch_apply函数能进行快速迭代遍历
dispatch_apply(10, dispatch_get_global_queue(0, 0), ^(size_t index){ // 执行10次代码,index顺序不确定 // 和for循环不同,不是有序的 // 它是同时并发遍历,一起做事情,快速遍历迭代 // 比如剪切图片的例子});
应用---队列组
有这么1种需求
首先:分别异步执行2个耗时的操作
其次:等2个异步操作都执行完毕后,再回到主线程执行操作
如果想要快速高效地实现上述需求,可以考虑用队列组。
dispatch_group_t group = dispatch_group_create();dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // 执行1个耗时的异步操作});dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // 执行1个耗时的异步操作});dispatch_group_notify(group, dispatch_get_main_queue(), ^{ // 等前面的异步操作都执行完毕后,回到主线程...});
Demo-核心代码
- (void)group{ dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); // 创建一个队列组 dispatch_group_t group = dispatch_group_create(); // 1.下载图片1 dispatch_group_async(group, queue, ^{ // 图片的网络路径 NSURL *url = [NSURL URLWithString:@"http://img.pconline.com.cn/images/photoblog/9/9/8/1/9981681/200910/11/1255259355826.jpg"]; // 加载图片 NSData *data = [NSData dataWithContentsOfURL:url]; // 生成图片 self.image1 = [UIImage imageWithData:data]; }); // 2.下载图片2 dispatch_group_async(group, queue, ^{ // 图片的网络路径 NSURL *url = [NSURL URLWithString:@"http://pic38.nipic.com/20140228/5571398_215900721128_2.jpg"]; // 加载图片 NSData *data = [NSData dataWithContentsOfURL:url]; // 生成图片 self.image2 = [UIImage imageWithData:data]; }); // 可以用barrier,先做前面两个,再做后面的任务 // 这里用队列组,前面的任务都放进自己的一个组,你的队列属于自己的组,前面两个组不管你谁先执行,都执行完后,再执行dispatch_group_notify里面的东西 // 3.将图片1、图片2合成一张新的图片 // 图片合成用绘图技术 dispatch_group_notify(group, queue, ^{ // 开启新的图形上下文 UIGraphicsBeginImageContext(CGSizeMake(100, 100)); // 绘制图片 [self.image1 drawInRect:CGRectMake(0, 0, 50, 100)]; [self.image2 drawInRect:CGRectMake(50, 0, 50, 100)]; // 取得上下文中的图片 UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); // 结束上下文 UIGraphicsEndImageContext(); // 回到主线程显示图片 dispatch_async(dispatch_get_main_queue(), ^{ // 4.将新图片显示出来 self.imageView.image = image; }); });}/** * 快速迭代 */- (void)apply{ dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); NSString *from = @"/Users/xiaomage/Desktop/From"; NSString *to = @"/Users/xiaomage/Desktop/To"; // 这里剪切文件完全可以同时进行,用子线程包起来 NSFileManager *mgr = [NSFileManager defaultManager]; NSArray *subpaths = [mgr subpathsAtPath:from]; dispatch_apply(subpaths.count, queue, ^(size_t index) { NSString *subpath = subpaths[index]; NSString *fromFullpath = [from stringByAppendingPathComponent:subpath]; NSString *toFullpath = [to stringByAppendingPathComponent:subpath]; // 剪切 [mgr moveItemAtPath:fromFullpath toPath:toFullpath error:nil]; NSLog(@"%@---%@", [NSThread currentThread], subpath); });}/** * 传统文件剪切 */- (void)moveFile{ NSString *from = @"/Users/xiaomage/Desktop/From"; NSString *to = @"/Users/xiaomage/Desktop/To"; NSFileManager *mgr = [NSFileManager defaultManager]; NSArray *subpaths = [mgr subpathsAtPath:from]; for (NSString *subpath in subpaths) { NSString *fromFullpath = [from stringByAppendingPathComponent:subpath]; NSString *toFullpath = [to stringByAppendingPathComponent:subpath]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // 剪切 [mgr moveItemAtPath:fromFullpath toPath:toFullpath error:nil]; }); }}- (void)once{ static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ NSLog(@"------run"); });}/** * 延迟执行 */- (void)delay{ NSLog(@"touchesBegan-----"); // [self performSelector:@selector(run) withObject:nil afterDelay:2.0]; // dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ // NSLog(@"run-----"); // }); [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:NO];}- (void)run{ NSLog(@"run-----");}- (void)barrier{ dispatch_queue_t queue = dispatch_queue_create("12312312", DISPATCH_QUEUE_CONCURRENT); dispatch_async(queue, ^{ NSLog(@"----1-----%@", [NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"----2-----%@", [NSThread currentThread]); }); dispatch_barrier_async(queue, ^{ NSLog(@"----barrier-----%@", [NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"----3-----%@", [NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"----4-----%@", [NSThread currentThread]); });}
- 使用GCD
- 使用GCD
- 使用GCD
- 使用GCD
- 使用GCD
- 使用GCD
- 使用GCD
- 使用GCD
- 使用GCD
- 使用GCD
- 使用GCD
- 使用GCD
- GCD使用
- 使用GCD
- gcd 使用
- 使用GCD
- 使用GCD
- 使用GCD
- 第65课:SparkSQL下Parquet深入进阶学习笔记
- Android设计模式应用-代理模式
- Bound Services绑定服务
- [noi2005][treap]序列维护
- Python序列概述
- GCD使用
- NYOJ 737石子合并(一)
- Http头:only-if-cached
- Cocoapods的安装和使用
- CSUST 校赛-G.哥德巴赫猜想
- Android Interface Definition Language (AIDL)
- 高精度模板
- 自己动手写注解
- 学习笔记