多线程 - 08.GCD其他使用
来源:互联网 发布:网络兼职怎么做 编辑:程序博客网 时间:2024/06/06 15:45
1.GCD线程之间的通信
- 使用异步函数+除了主队列之外的队列创建子线程,在子线程中执行下载操作(耗时操作)
- 在子线程中添加任务到主队列(更新UI操作),同步异步都可
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ // 1.创建并发队列 dispatch_queue_t queue = dispatch_get_global_queue(0, 0); // 2.调用异步函数,新建子线程,做好事操作 dispatch_async(queue, ^{ // 2.1.下载图片 NSURL *url = [NSURL URLWithString:@"http://pic.4j4j.cn/upload/pic/20130531/07ed5ea485.jpg"]; NSData *data = [NSData dataWithContentsOfURL:url]; // 2.2 将二进制转换为图片 UIImage *image = [UIImage imageWithData:data]; // 2.3 回到主线程更新UI /* 技巧: 如果想等UI更新完毕再执行后面的代码, 那么使用同步函数 如果不想等UI更新完毕就需要执行后面的代码, 那么使用异步函数 */ dispatch_sync(dispatch_get_main_queue(), ^{ self.iv.image = image; }); NSLog(@"设置图片完毕 %@", image); });}
2.延时操作
- 1.利用定时器实现
[NSTimer scheduledTimerWithTimeInterval:3.0 target:self selector:@selector(demo) userInfo:nil repeats:NO];-(void)demo{ NSLog(@"延时操作");}
- 2.利用performSelector方法
[self performSelector:@selector(demo) withObject:nil afterDelay:3.0];-(void)demo{ NSLog(@"延时操作");}
- 3.利用GCD的dispatch_after方法
-(void)delayGCD{ // 第一个参数输入需要延时的时间,单位纳秒 // block为延时操作任务 // 该方法中, 会根据传入的队列来决定回掉block在哪个线程中执行 // 如果传入的是主队列, 那么block会在主线程调用 // 如果传入的是全局队列, 那么block会在子线程中调用 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ NSLog(@"3秒后执行 %@",[NSThread currentThread]); });}
3.一次性代码
- 注意,一次性代码永远只执行一次
- 一次性代码和懒加载不能混用,懒加载在需要的时候被创建,销毁后,再次加载仍然会重新创建,而一次性代码在整个程序过程中只会被执行一次
- 通常一次性代码可以用来创建单例对象
-(void)onceTakon{ /* 静态变量用来记录,代码是否被执行,并且一次性代码默认是线程安全的 */ static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ NSLog(@"一次性代码"); });}
4.快速迭代
- 使用dispatch_apply函数能进行快速迭代遍历
- 使用快速迭代要比for循环遍历效率要高
// 快速迭代-(void)apply{ // 获取文件路径 NSString *sourceFile = @"/Users/liuzhouji/Desktop/abc"; NSString *resultFile = @"/Users/liuzhouji/Desktop/zj"; // 获取原文件中所有内容 NSFileManager *manager = [NSFileManager defaultManager]; NSArray *files = [manager subpathsAtPath:sourceFile]; // 遍历数组,拼接文件路径 /* 参数解释 第一个参数: 需要遍历几次 第二个参数: 决定第三个参数的block在哪个线程中执行 第三个参数: 回掉 */ dispatch_apply(files.count, dispatch_get_global_queue(0, 0), ^(size_t idx) { // 获取每一个文件名 NSString *fileName = files[idx]; // 生成原文件和目标文件的绝对路径 NSString *sourcePath = [sourceFile stringByAppendingPathComponent:fileName]; NSString *desPath = [resultFile stringByAppendingPathComponent:fileName]; // 利用fileManager拷贝文件 [manager moveItemAtPath:sourcePath toPath:desPath error:nil]; });}
5.栅栏
- 功能:
- 1.拦截前面的任务, 只有先添加到队列中的任务=执行完毕, 才会执行栅栏添加的任务
- 2.如果栅栏后面还有其它的任务,那么必须等栅栏执行完毕才会执行后面的其它任务
- 注意点:
- 1.如果想要使用栅栏, 那么就不能使用全局的并发队列
- 2.如果想使用栅栏,那么所有的任务都必须添加到同一个队列中
/** * 栅栏,实现等待图片下载完毕之后再执行刷新UI的操作 */- (void)barrier{ dispatch_queue_t queue = dispatch_queue_create("zj.queue", DISPATCH_QUEUE_CONCURRENT); __block UIImage *image1 = nil; __block UIImage *image2 = nil; // 1.开启一个新的线程下载第一张图片 dispatch_async(queue, ^{ NSURL *url = [NSURL URLWithString:@"http://h.hiphotos.baidu.com/image/pic/item/77c6a7efce1b9d1632701663f5deb48f8c546479.jpg"]; NSData *data = [NSData dataWithContentsOfURL:url]; UIImage *image = [UIImage imageWithData:data]; image1 = image; NSLog(@"图片1下载完毕"); }); // 2.开启一个新的线程下载第二张图片 dispatch_async(queue, ^{ NSURL *url = [NSURL URLWithString:@"http://f.hiphotos.baidu.com/image/pic/item/18d8bc3eb13533fa0f2eb8c0acd3fd1f40345b47.jpg"]; NSData *data = [NSData dataWithContentsOfURL:url]; UIImage *image = [UIImage imageWithData:data]; image2 = image; NSLog(@"图片2下载完毕"); }); // 3.开启一个新的线程, 合成图片 // 栅栏 // 功能: // 1.拦截前面的任务, 只有先添加到队列中的任务=执行完毕, 才会执行栅栏添加的任务 // 2.如果栅栏后面还有其它的任务, 那么必须等栅栏执行完毕才会执行后面的其它任务 // 注意点: // 1.如果想要使用栅栏, 那么就不能使用全局的并发队列 // 2.如果想使用栅栏, 那么所有的任务都必须添加到同一个队列中 dispatch_barrier_async(queue, ^{ NSLog(@"%@ %@", image1, image2); // 1.开启图片上下文 UIGraphicsBeginImageContext(CGSizeMake(200, 200)); // 2.将第一张图片画上去 [image1 drawInRect:CGRectMake(0, 0, 100, 200)]; // 3.将第二张图片画上去 [image2 drawInRect:CGRectMake(100, 0, 100, 200)]; // 4.从上下文中获取绘制好的图片 UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); // 5.关闭上下文 UIGraphicsEndImageContext(); // 4.回到主线程更新UI dispatch_async(dispatch_get_main_queue(), ^{ self.iv.image = newImage; [UIImagePNGRepresentation(newImage) writeToFile:@"/Users/xiaomage/Desktop/abc/123.png" atomically:YES]; }); NSLog(@"栅栏执行完毕了"); }); dispatch_async(queue, ^{ NSLog(@"1---------"); }); dispatch_async(queue, ^{ NSLog(@"2---------"); }); dispatch_async(queue, ^{ NSLog(@"3---------"); }); /*输出结果: 图片1下载完毕 图片2下载完毕 栅栏执行完毕了 2--------- 1--------- 3--------- */}
6.队列组
- 利用队列组可以实现和栅栏类似的效果
- 可以让耗时操作执行完后再去执行更新UI的操作
-(void)group{ // 创建队列 dispatch_queue_t queue = dispatch_get_global_queue(0, 0); // 创建组 dispatch_group_t group = dispatch_group_create(); __block UIImage *image1 = nil; __block UIImage *image2 = nil; // 添加队列到队列组 // 下载第一张图片 dispatch_group_async(group, queue, ^{ NSURL *url = [NSURL URLWithString:@"http://h.hiphotos.baidu.com/image/pic/item/77c6a7efce1b9d1632701663f5deb48f8c546479.jpg"]; NSData *data = [NSData dataWithContentsOfURL:url]; UIImage *image = [UIImage imageWithData:data]; image1 = image; NSLog(@"图片1下载完毕"); }); // 下载第二张图片 dispatch_group_async(group, queue, ^{ NSURL *url = [NSURL URLWithString:@"http://f.hiphotos.baidu.com/image/pic/item/18d8bc3eb13533fa0f2eb8c0acd3fd1f40345b47.jpg"]; NSData *data = [NSData dataWithContentsOfURL:url]; UIImage *image = [UIImage imageWithData:data]; image2 = image; NSLog(@"图片2下载完毕"); }); // 只要将队列放到group中, 队列中的任务执行完毕, group就会发出一个通知 dispatch_group_notify(group, queue, ^{ NSLog(@"%@ %@", image1, image2); // 1.开启图片上下文 UIGraphicsBeginImageContext(CGSizeMake(200, 200)); // 2.将第一张图片画上去 [image1 drawInRect:CGRectMake(0, 0, 100, 200)]; // 3.将第二张图片画上去 [image2 drawInRect:CGRectMake(100, 0, 100, 200)]; // 4.从上下文中获取绘制好的图片 UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); // 5.关闭上下文 UIGraphicsEndImageContext(); // 回到主线程,更新UI dispatch_async(dispatch_get_main_queue(), ^{ self.iv.image = newImage; [UIImagePNGRepresentation(newImage) writeToFile:@"/Users/xiaomage/Desktop/abc/123.png" atomically:YES]; }); });}
0 0
- 多线程 - 08.GCD其他使用
- 使用GCD实现多线程
- 多线程GCD的使用
- GCD使用与多线程
- 多线程GCD的使用
- 多线程GCD的使用
- 多线程GCD的使用
- 多线程GCD的使用
- 多线程GCD的使用
- 多线程GCD的使用
- iOS多线程GCD使用
- 多线程GCD的使用
- ios多线程 GCD使用
- 使用GCD创建多线程
- 多线程GCD的使用
- iOS GCD多线程使用
- 多线程:GCD 基本使用
- GCD多线程的使用
- 黑马程序员_递归、IO-字符流笔记
- VBScript脚本要参考的网址
- android 电容屏(三):驱动调试之驱动程序分析篇
- C,C++,Java语言中static作用的辨析
- 最近再弄jsoncpp 遇到的初级问题
- 多线程 - 08.GCD其他使用
- iOS开发 -- 图片轮播(详解)
- 多线程 - 09.NSOperation基本使用
- 每日5题(spring)
- AutoHotKey实现百度云批量离线下载工具
- 黑马程序员_字节流、缓冲流
- shell 常见的系统环境变量解析
- android 电容屏(四):驱动调试之驱动程序分析篇 -- FocalTech
- Java- 对象构造与初始化