线程间通讯

一、NSThread

1.简单说明

①线程间通信:在1个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信

②线程间通信的体现

  • 1个线程传递数据给另1个线程
  • 在1个线程中执行完特定任务后,转到另1个线程继续执行任务

③线程间通信常用方法

// waitUntilDone的含义:
// 如果传入的是YES: 那么会等到主线程中的方法执行完毕, 才会继续执行下面其他行的代码
// 如果传入的是NO: 那么不用等到主线程中的方法执行完毕, 就可以继续执行下面其他行的低吗 /*
* 回到主线程执行,执行self的showImage方法,参数是image
*/
[self performSelectorOnMainThread:@selector(showImage:) withObject:image waitUntilDone:YES]; /*
* 回到xx线程执行aSelector方法,参数是arg
*/
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait;

④案例,下载图片,然后在屏幕上显示

注意:虽然有时候可以在子线程中操作UI,但是开发中千万不要这样干因为如果是在子线程中操作UI, 有时候行, 有时候不行
- (void)viewDidLoad
{
// 1.给定图片的url
NSURL *url = [NSURL URLWithString:@"http://b.hiphotos.baidu.com/image/pic/item/e4dde71190ef76c666af095f9e16fdfaaf516741.jpg"];
// 2.开启线程,在后台执行download方法
[self performSelectorInBackground:@selector(download:) withObject:url];
} - (void)download:(NSURL *)url
{
// 在子线程下载图片
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data]; // 设置图片,执行self.imageView的setImage:方法
// [self.imageView performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:YES]; // 另一张设置图片的方法
// 回到主线程中执行 showImage:方法,在此方法中设置图片
[self performSelector:@selector(showImage:) onThread:[NSThread mainThread] withObject:image waitUntilDone:YES]; } -(void)showImage:(UIImage *)image
{
// 更新UI
self.imageView.image = image;
}

几个常用打印时间的方法

    //获得当前时间,double型
CFAbsoluteTime begin = CFAbsoluteTimeGetCurrent(); // 获得当前时间
NSDate *begin = [NSDate date];
// 执行一些操作之后的时间
NSDate *end = [NSDate date];
// 时差
NSLog(@"花费了多少秒 %f", [end timeIntervalSinceDate:begin]);

二、GCD

  • 案例,下载图片,然后在屏幕上显示

在dispatch_get_main_queue() 队列中

如果是通过异步函数调用, 那么会先执行完所有的代码, 再更新UI
如果是同步函数调用, 那么会先更新UI, 再执行其它代码
 dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
// 1.下载图片(耗时)
dispatch_async(queue, ^{
NSLog(@"%@", [NSThread currentThread]);
// 1.创建URL
NSURL *url = [NSURL URLWithString:@"http://stimgcn1.s-msn.com/msnportal/ent/2015/08/04/7a59dbe7-3c18-4fae-bb56-305dab5e6951.jpg"];
// 2.通过NSData下载图片
NSData *data = [NSData dataWithContentsOfURL:url];
// 3.将NSData转换为图片
UIImage *image = [UIImage imageWithData:data]; // 4.更新UI
// self.imageView.image = image;
// NSLog(@"更新UI完毕");
// 如果是通过异步函数调用, 那么会先执行完所有的代码, 再更新UI
// 如果是同步函数调用, 那么会先更新UI, 再执行其它代码
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"%@", [NSThread currentThread]);
self.imageView.image = image;
NSLog(@"更新UI完毕");
});
NSLog(@"Other");
});

三、NSOperation

1.第一种方法

// 1.创建一个新的队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init]; // 2.添加任务(操作)
[queue addOperationWithBlock:^{
// 2.1在子线程中下载图片
NSURL *url = [NSURL URLWithString:@"http://imgcache.mysodao.com/img2/M04/8C/74/CgAPDk9dyjvS1AanAAJPpRypnFA573_700x0x1.JPG"];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data]; // 2.2回到主线程更新UI
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
self.imageView.image = image;
}];
}];

2.第二种方法(添加依赖)

/ 1.创建一个队列
// 一般情况下, 在做企业开发时候, 都会定义一个全局的自定义队列, 便于使用
NSOperationQueue *queue = [[NSOperationQueue alloc] init]; // 2.添加一个操作下载第一张图片
__block UIImage *image1 = nil;
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
NSURL *url = [NSURL URLWithString:@"http://imgcache.mysodao.com/img2/M04/8C/74/CgAPDk9dyjvS1AanAAJPpRypnFA573_700x0x1.JPG"];
NSData *data = [NSData dataWithContentsOfURL:url];
image1 = [UIImage imageWithData:data];
}]; // 3.添加一个操作下载第二张图片
__block UIImage *image2 = nil;
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
NSURL *url = [NSURL URLWithString:@"http://imgcache.mysodao.com/img1/M02/EE/B5/CgAPDE-kEtqjE8CWAAg9m-Zz4qo025-22365300.JPG"];
NSData *data = [NSData dataWithContentsOfURL:url];
image2 = [UIImage imageWithData:data];
}];
// 4.添加一个操作合成图片
NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
UIGraphicsBeginImageContext(CGSizeMake(200, 200));
[image1 drawInRect:CGRectMake(0, 0, 100, 200)];
[image2 drawInRect:CGRectMake(100, 0, 100, 200)];
UIImage *res = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext(); // 5.回到主线程更新UI
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
self.imageView.image = res;
}];
}]; // 6.添加依赖 [op3 addDependency:op1];
[op3 addDependency:op2]; // 7.添加操作到队列中
[queue addOperation:op1];
[queue addOperation:op2];
[queue addOperation:op3];

最新文章

  1. Quartz资源收藏
  2. 统计学 nested_design 嵌套设计
  3. IIS配置(安装IIS、.Net、更改IIS Log目录位置)
  4. Linux相关指令
  5. js判断是否在iframe中
  6. nodejs学习记录
  7. Linux学习-汇总
  8. C#设计模式(1)——简单工厂模式
  9. 【Android】LMK 工作机制
  10. 干货-递归下降分析器 笔记(具体看Python Cookbook, 3rd edition 的2.19章节)
  11. 阿里云ECS安装Kubernetes问题收集与解答
  12. Javascript权威指南阅读笔记--第3章类型、值和变量(1)
  13. Exp02
  14. [日志log] 常用log日志记录方式对比和详解
  15. layer弹出相册层
  16. 3D空间中射线与三角形的交叉检测算法【转】
  17. win10里如何在中文输入法里添加美式键盘
  18. CLR_Via_C#学习笔记之事件
  19. HDU1018 (斯特林公式)
  20. ECMAScript 定义类、对象

热门文章

  1. CodeChef Consecutive Snakes 三分(整数)
  2. 设计模式-(12)迭代器模式 (swift版)
  3. Tju 4119. HDFS
  4. 比特币交易(Transaction)的输入与输出
  5. POJ - 1470 Closest Common Ancestors(离线Tarjan算法)
  6. bzoj3195 [Jxoi2012]奇怪的道路——状压DP
  7. cmath函数整理
  8. Vue.js:安装node js到构建一个vue并启动它
  9. splay启发式合并
  10. ASP.NET验证控件CustomValidator客户端验证DropDownList、TextBox