队列组

让队列里的任务同时执行,当任务都执行完毕时,再以通知的形式告诉程序员。举例,同时下载两张图片,两张图片都下载完了,在合成成一张。

代码:

#import "ViewController.h"

@interface ViewController ()

@property (weak, nonatomic) IBOutlet UIImageView *imageView1;
@property (weak, nonatomic) IBOutlet UIImageView *imageView2;
@property (weak, nonatomic) IBOutlet UIImageView *imageView3;
@end @implementation ViewController
// 点击屏幕开始下载图片
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { // 创建全局并发队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 创建队列组
dispatch_group_t group = dispatch_group_create(); __block UIImage *image1 = nil;
// 开启一个任务
dispatch_group_async(group, queue, ^{
NSLog(@"%@开始下载第一张图片",[NSThread currentThread]);
NSString *strURL1 = @"http://h.hiphotos.baidu.com/zhidao/pic/item/6d81800a19d8bc3ed69473cb848ba61ea8d34516.jpg";
image1 = [self downloadImageWithURL:strURL1];
}); // 开启一个任务
__block UIImage *image2 = nil;
dispatch_group_async(group, queue, ^{
NSLog(@"%@开始下载第二张图片",[NSThread currentThread]);
NSString *strURL2 = @"http://h.hiphotos.baidu.com/zhidao/pic/item/0eb30f2442a7d9334f268ca9a84bd11372f00159.jpg";
image2 = [self downloadImageWithURL:strURL2];
}); // 同时执行下载图片1\下载图片2的操作 // 等group里的任务执行完毕,执行的操作
// 回到主线程显示图片
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"%@显示图片",[NSThread currentThread]);
self.imageView1.image = image1;
self.imageView2.image = image2;
// 合并两张图片图片
UIGraphicsBeginImageContextWithOptions(CGSizeMake(100, 50), NO, 0.0);
[image1 drawInRect:CGRectMake(0, 0, 50, 50)];
[image2 drawInRect:CGRectMake(50, 0, 50, 50)];
self.imageView3.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
});
}
- (UIImage *)downloadImageWithURL : (NSString *)strURL {
NSURL *url = [NSURL URLWithString:strURL];
return [UIImage imageWithData:[NSData dataWithContentsOfURL:url]];
}
@end

日志

2016-11-05 09:03:49.300 TTTTTTTTTT[2543:26927] <NSThread: 0x7ba80500>{number = 3, name = (null)}开始下载第一张图片
2016-11-05 09:03:49.301 TTTTTTTTTT[2543:28894] <NSThread: 0x7ba80b10>{number = 4, name = (null)}开始下载第二张图片
2016-11-05 09:03:49.453 TTTTTTTTTT[2543:26806] <NSThread: 0x79773680>{number = 1, name = main}显示图片

效果:

如果不用队列组,下载第一张图片、下载第二张图片、合并两张图片,就只能当做一个任务放入队列中,不能同时下载两张图片,耗时几乎多了一倍。因为,如果你不这样做(当做一个任务放入队列中),你不知道两张图片什么时候下载完,谁先下载完,因为每次都不确定,不知道什么时候合并图片。现在用group,由系统来帮我们监听两张图片下载的进度,咱们只要把两张图片都下载完的程序写写进dispatch_group_notify就好了。

延迟执行

延迟执行就是让程序过一会在执行某一段代码。用两种方法:

- (void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay;
dispatch_after(dispatch_time_t when,
dispatch_queue_t queue,
dispatch_block_t block);

代码

- (void)viewDidLoad {
[super viewDidLoad];
// 第一种
[self performSelector:@selector(run) withObject:nil afterDelay:2];
// 第二种 可以安排执行的队列 3秒后执行
// 主队列
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"当前线程2%@",[NSThread currentThread]);
NSLog(@"GCD主队列过一会执行我");
});
// 全局并发队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), queue, ^{
NSLog(@"当前线程3%@",[NSThread currentThread]);
NSLog(@"GCD全局并发队列过一会执行我");
});
}
- (void)run {
NSLog(@"当前线程1%@",[NSThread currentThread]);
NSLog(@"过一会执行我");
}

日志

2016-11-05 09:27:04.903 TTTTTTTTTT[3439:39246] 当前线程1<NSThread: 0x7b6629a0>{number = 1, name = main}
2016-11-05 09:27:04.903 TTTTTTTTTT[3439:39246] 过一会执行我
2016-11-05 09:27:06.176 TTTTTTTTTT[3439:39246] 当前线程2<NSThread: 0x7b6629a0>{number = 1, name = main}
2016-11-05 09:27:06.176 TTTTTTTTTT[3439:39291] 当前线程3<NSThread: 0x7d175a90>{number = 3, name = (null)}
2016-11-05 09:27:06.177 TTTTTTTTTT[3439:39246] GCD主队列过一会执行我
2016-11-05 09:27:06.177 TTTTTTTTTT[3439:39291] GCD全局并发队列过一会执行我

  延迟执行我们常用的可能是第一种方法。从那个线程中调用“ performSelector”,run方法就在哪个线程中执行可,一般是主线程。第二种方法是可以自定义方法执行的队列,可以是主队列,也可以是全局队列。本人比较喜欢用block,所以喜欢第二种,因为都写在一起,增加了代码的可读性。

一次性代码

  一次性代码主要是在单例中应用。

#import "Person.h"

@implementation Person

static Person *person;
// 1
- (instancetype)shareInstance1 { static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
person = [[Person alloc] init];
});
return person;
}
// 2.
- (instancetype)shareInstace2 { if (!person) {
person = [[Person alloc] init];
}
return person;
}
@end

  dispatch_once里的代码在整个程序运行过程中就执行一次!!!所以你有这方面的需求,也可以用这个。

  其实关于GCD,今天是最后一篇文章了,其实GCD还有很多地方我没有讲到,一方面是我水平有限,一方面是不常用。从下一篇开始,我就开始讲NSOperation了。例外,如果大家关于GCD还有什么想知道的,可以留言,我知道的一定告诉。

最新文章

  1. python 解析XML python模块xml.dom解析xml实例代码
  2. VC++ MFC 如何实现在编辑框中输出具有换行功能的文段 01
  3. 《The Google File System》论文阅读笔记——GFS设计原理
  4. 基于GBT28181:SIP协议组件开发-----------第二篇SIP组件开发原理
  5. Android testing tools
  6. hdu 1242 Rescue_bfs+优先队列
  7. nyoj 325 zb的生日(dfs)
  8. 关于switch的思考和总结
  9. hdu 4342 History repeat itself(数学题)
  10. PID控制学习笔记(二)
  11. sock
  12. 智能合约语言 Solidity 教程系列3 - 函数类型
  13. Spring MVC 使用介绍(六)—— 注解式控制器(二):请求映射与参数绑定
  14. jQuery常见用法
  15. Intellij IDEA 自动清除无效 import
  16. HTML 中获取现在时间,实时时间获取
  17. Eclipse通用设置
  18. BZOJ3198 [Sdoi2013]spring 哈希 容斥原理
  19. javascript公有静态成员
  20. Spring AOP源码分析(一)使用示例

热门文章

  1. JAVA基础代码分享--模拟人机猜拳系统
  2. NFS Volume Provider(Part III) - 每天5分钟玩转 OpenStack(64)
  3. VS2015 Enterprise 安装之惊险及收获
  4. Visual Studio常用小技巧一:代码段+快捷键+插件=效率
  5. 【记录】ASP.NET MVC MapRoute .htm 不起作用
  6. 【记录】JS 生成 URL 二维码
  7. (十二) WebGIS中矢量图层的设计
  8. 一张图看懂normal,static,sealed,abstract 的 区别
  9. 【Android】《App研发录》总结
  10. 使用AutoMapper进行对象间映射