1、GCD是什么。安全
GCD 是 libdispatch 的市场名称,而 libdispatch 做为 Apple 的一个库,为并发代码在多核硬件(跑 iOS 或 OS X )上执行提供有力支持。网络
它具备如下优势:
1.GCD 能经过推迟昂贵计算任务并在后台运行它们来改善你的应用的响应性能。
2.GCD 提供一个易于使用的并发模型而不单单只是锁和线程,以帮助咱们避开并发陷阱。
3.GCD 具备在常见模式(例如单例)上用更高性能的原语优化你的代码的潜在能力。
并发
2、系统提供的用法
app
为了方便GCD的使用,苹果提供了一些方法方便咱们将Block放在主线程或者后台线程或者延后执行。异步
//子线程执行async
dispatch_async(dispatch_get_global_queue(0, 0), ^{函数
//something性能
});优化
//主线程执行ui
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
});
3、应用---延时
(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.将图片一、图片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]);
});
}