线程间通讯

一、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];

iOS--多线程之线程间通讯的更多相关文章

  1. 黑马程序员——JAVA基础之多线程的线程间通讯等

    ------- android培训.java培训.期待与您交流! ---------- 线程间通讯: 其实就是多个线程在操作同一个资源,但是动作不同. wait(); 在其他线程调用此对象的notif ...

  2. 【原】iOS多线程之线程间通信和线程互斥

    线程间通信 1> 线程间通信分为两种 主线程进入子线程(前面的方法都可以) 子线程回到主线程 2> 返回主线程 3> 代码 这个案例的思路是:当我触摸屏幕时,会在子线程加载图片,然后 ...

  3. Android 异步任务,通过PHP访问数据库,多线程,线程间通讯

    文章列表MainActivity.java package com.eric.asynctask; import java.io.IOException; import java.util.Array ...

  4. iOS开发多线程-线程间通讯

    一.NSThread 线程间的通讯 - (void)demoAboutNSThread { NSLog(@"demoAboutNSThread %@", [NSThread cur ...

  5. java 并发性和多线程 -- 读感 (二 线程间通讯,共享内存的机制)

    参考文章:http://ifeve.com/java-concurrency-thread-directory/ 其中的竞态,线程安全,内存模型,线程间的通信,java ThreadLocal类小节部 ...

  6. Java:多线程<三>死锁、线程间通讯

    死锁: 同步嵌套同步,而且使用的锁不是同一把锁时就可能出现死锁 class Test implements Runnable { private boolean flag; Test(boolean ...

  7. iOS开发多线程篇—线程间的通信

    iOS开发多线程篇—线程间的通信 一.简单说明 线程间通信:在1个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信 线程间通信的体现 1个线程传递数据给另1个线程 在1个线程中执行完特定任 ...

  8. 【转】JAVA 并发性和多线程 -- 读感 (二 线程间通讯,共享内存的机制)

    原文地址:https://www.cnblogs.com/edenpans/p/6020113.html 参考文章:http://ifeve.com/java-concurrency-thread-d ...

  9. (转载)Java里快如闪电的线程间通讯

    转自(http://www.infoq.com/cn/articles/High-Performance-Java-Inter-Thread-Communications) 这个故事源自一个很简单的想 ...

  10. Java中快如闪电的线程间通讯

    这个故事源自一个很简单的想法:创建一个对开发人员友好的.简单轻量的线程间通讯框架,完全不用锁.同步器.信号量.等待和通知,在Java里开发一个轻量.无锁的线程内通讯框架:并且也没有队列.消息.事件或任 ...

随机推荐

  1. Django模板语言(二)

    1,装饰器:在不改变原函数的调用方式情况下为原函数增加一些功能(遵循开放封闭的原则) def outter(fn): def inner(*args, **kwargs): # 可以在执行函数前执行一 ...

  2. PR 修改保存的增强 ME_UPDATE_REQUISITION

    FUNCTION me_update_requisition."""""""""""&qu ...

  3. mongodb02

    memcached redis : kv数据库(key/value) mongodb 文档数据库,存储的是文档(Bson->json对象二进制化后叫bson,js的二进制对象,引擎是用js实现的 ...

  4. 从sp_executesql中返回table型数据及动态SQL语句的参数化查询

    在返回分页数据时,我们会经常会用到参数化传递过滤条件,如何拼接SQL语句成了一个难题. 我们可以这样拼接: exec('sp_executesql sql语句,参数定义,参数值') sql语句和参数定 ...

  5. JS数组array常用方法

    JS数组array常用方法 1.检测数组 1)检测对象是否为数组,使用instanceof 操作符 if(value instanceof Array) { //对数组执行某些操作 } 2)获取对象的 ...

  6. JAVASCRIPT 和 AJax 实现局部验证

    JSP页面 <td width="10%" class="main_matter_td">真实姓名</td> <td width= ...

  7. 并不对劲的cdq分治解三维偏序

    为了反驳隔壁很对劲的太刀流,并不对劲的片手流决定与之针锋相对,先一步发表cdq分治解三维偏序. 很对劲的太刀流在这里->  参照一.二维偏序的方法,会发现一位偏序就是直接排序,可以看成通过排序使 ...

  8. [九省联考2018]一双木棋chess——搜索+哈希

    题目:bzoj5248 https://www.lydsy.com/JudgeOnline/problem.php?id=5248 洛谷P4363 https://www.luogu.org/prob ...

  9. 深入理解JMM(Java内存模型) --(一)

    并发编程模型的分类 在并发编程中,我们需要处理两个关键问题:线程之间如何通信及线程之间如何同步(这里的线程是指并发执行的活动实体).通信是指线程之间以何种机制来交换信息.在命令式编程中,线程之间的通信 ...

  10. JAVA JVM 流程二

    作为一名Java使用者,掌握JVM的体系结构也是必须的.说起Java,人们首先想到的是Java编程语言,然而事实上,Java是一种技术,它由四方面组成:Java编程语言.Java类文件格式.Java虚 ...