iOS 多线程(NSThread、GCD、NSOperation)
ios中得多线程技术主要使用3种:NSThread、NSOperation和GCD
一、NSThread: 最轻量级方法,但是不安全需要手动加锁,需要自己管理生命周期
NSThread的使用方法有2种:
// 第一种,需要start
1 NSThread *th1 = [[NSThread alloc] initWithTarget:self selector:@selector(btnClick) object:nil];
[th1 setName:@"线程1"];
[th1 start];
// 第二种
1 [NSThread detachNewThreadSelector:@selector(btnClick) toTarget:self withObject:nil];
因为NSThread使用不安全,我们需要给它加锁(主要的实现代码):
@property (nonatomic,assign) NSInteger fruits;
@property (nonatomic,strong) NSLock *lock;
- (void)viewDidLoad
{
[super viewDidLoad]; _lock = [[NSLock alloc] init];
_fruits = ;
} - (void)btnClick
{
@synchronized(_lock){ // 加锁 while (_fruits > ) { NSLog(@"当前线程为:%@ , 剩余票数为:%d",[NSThread currentThread], _fruits); _fruits--;
}
}
}
二、GCD:(Grand Central Dispatch)是一种多核编码技术,用纯C语言编写。
异步:具备开启线程的功能
同步:不具备开启线程的功能
并行队列:多个任务可以同时执行
串行队列:执行完一个任务后再执行下一个任务
下面来进行用代码说明:
// 自定义异步方法
- (void)async:(dispatch_queue_t)queue
{
// 异步执行
dispatch_async(queue, ^{ NSLog(@"im1-%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{ NSLog(@"im2-%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{ NSLog(@"im3-%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{ NSLog(@"im4-%@",[NSThread currentThread]);
}); }
// 自定义同步方法
- (void)sync:(dispatch_queue_t)queue
{
// 同步执行
dispatch_sync(queue, ^{ NSLog(@"im1-%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{ NSLog(@"im2-%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{ NSLog(@"im3-%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{ NSLog(@"im4-%@",[NSThread currentThread]);
}); }
调用异步执行方法:
// 创建一个全局并行队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, ); // 异步执行
[self async:queue];
最终的结果为:开启了四个线程,并且执行顺序是不定
-- ::20.438 GCD[:1f07] im3-<NSThread: 0x7177ee0>{name = (null), num = }
-- ::20.432 GCD[:] im1-<NSThread: 0x7177d70>{name = (null), num = }
-- ::20.440 GCD[:] im4-<NSThread: 0x7178490>{name = (null), num = }
-- ::20.432 GCD[:1a03] im2-<NSThread: 0x75429f0>{name = (null), num = }
// 创建一个全局串行队列
dispatch_queue_t queue = dispatch_queue_create("wys", NULL); // 异步执行
[self async:queue];
最终的结果为:开启了一个线程,执行顺序为从上往下依次执行
-- ::19.415 GCD[:] im1-<NSThread: 0x71631a0>{name = (null), num = }
-- ::19.428 GCD[:] im2-<NSThread: 0x71631a0>{name = (null), num = }
-- ::19.437 GCD[:] im3-<NSThread: 0x71631a0>{name = (null), num = }
-- ::19.450 GCD[:] im4-<NSThread: 0x71631a0>{name = (null), num = }
调用主队列执行方法:
// 创建主队列
dispatch_queue_t queue = dispatch_get_main_queue(); // 异步执行
[self async:queue];
最红的结果为:顺序执行并且不开启线程,在主线程中执行
-- ::45.320 GCD[:c07] im1-<NSThread: 0x71560c0>{name = (null), num = }
-- ::45.333 GCD[:c07] im2-<NSThread: 0x71560c0>{name = (null), num = }
-- ::45.339 GCD[:c07] im3-<NSThread: 0x71560c0>{name = (null), num = }
-- ::45.347 GCD[:c07] im4-<NSThread: 0x71560c0>{name = (null), num = }
// 创建主队列
dispatch_queue_t queue = dispatch_get_main_queue(); NSLog(@"start"); // 同步执行
[self sync:queue]; NSLog(@"end");
最终的结果为:执行到start就卡住了,不能往下执行
-- ::12.856 GCD[:c07] start
调用同步执行方法:
// 创建全局并行队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, ); // 同步执行
[self sync:queue];
最终的结果为:不开启线程,并且顺序执行,直接主线程执行
-- ::27.448 GCD[:c07] im1-<NSThread: 0x71133c0>{name = (null), num = }
-- ::27.458 GCD[:c07] im2-<NSThread: 0x71133c0>{name = (null), num = }
-- ::27.468 GCD[:c07] im3-<NSThread: 0x71133c0>{name = (null), num = }
-- ::27.472 GCD[:c07] im4-<NSThread: 0x71133c0>{name = (null), num = }
// 创建串行队列
dispatch_queue_t queue = dispatch_queue_create("wys", NULL); // 同步执行
[self sync:queue];
最终的结果为:不开启线程,并且顺序执行,直接主线程执行
-- ::40.609 GCD[:c07] im1-<NSThread: 0x713e570>{name = (null), num = }
-- ::40.621 GCD[:c07] im2-<NSThread: 0x713e570>{name = (null), num = }
-- ::40.626 GCD[:c07] im3-<NSThread: 0x713e570>{name = (null), num = }
-- ::40.634 GCD[:c07] im4-<NSThread: 0x713e570>{name = (null), num = }
多线程之间的通信:UI界面的更新一定要在主线程中执行
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, ), ^{ // 全局并行队列异步执行
NSLog(@"全局并行队列异步执行 - %@",[NSThread currentThread]);
// 获取网络图片数据
NSString *str = @"https://ss0.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=3384245408,2851245305&fm=21&gp=0.jpg";
NSURL *url = [NSURL URLWithString:str];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data];
dispatch_async(dispatch_get_main_queue(), ^{ // 主线程异步执行
NSLog(@"主线程异步执行 - %@",[NSThread currentThread]);
// 更新界面
[_im1 setImage:image];
});
});
最终的结果为:
-- ::08.513 GCD[:] 全局并行队列异步执行 -<NSThread: 0x754c530>{name = (null), num = }
-- ::10.657 GCD[:c07] 主线程异步执行 -<NSThread: 0x7132c80>{name = (null), num = }
利用多线程来实现延时执行:
1、利用GCD
double delayInSeconds = 2.0; // 延时时长
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ // 在主线程中执行 NSLog(@"%@",[NSThread currentThread]); // 更新界面
[_im1 setImage:image]; });
2、利用此方法,performSelector为你要调用的方法,withObject为你要传得值,afterDelay为延时时长
[self performSelector:@selector(downLoad) withObject:nil afterDelay:0.5f];
队列组:
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, ); dispatch_group_async(group, queue, ^{ // 代码1
}); dispatch_group_async(group, queue, ^{ // 代码2
}); dispatch_group_notify(group, queue, ^{ // 执行完代码1和代码2后,再执行此方法
});
三、NSOperation:基于GCD,能控制最大并发线程数,主要有2个类:NSInvocationOperation和NSBlockOperation
其步骤为: 创建队列、添加操作、将操作添加到队列
A、NSInvocationOperation:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
NSOperationQueue *queue = [[NSOperationQueue alloc] init]; NSInvocationOperation *invo = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(buy) object:nil]; [queue addOperation:invo]; } - (void)buy
{
NSLog(@"%@",[NSThread currentThread]);
}
最后的结果为:开启了一个线程
-- ::54.060 op1[:1e07] <NSThread: 0x71a6de0>{name = (null), num = }
B、NSBlockOperation
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSBlockOperation *b1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"111--%@",[NSThread currentThread]);
}];
NSBlockOperation *b2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"222--%@",[NSThread currentThread]);
}];
NSBlockOperation *b3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"333--%@",[NSThread currentThread]);
}];
[queue addOperation:b1];
[queue addOperation:b2];
[queue addOperation:b3];
最后的结果为:开启了三个线程,自动异步执行
-- ::59.897 op1[:1a03] --<NSThread: 0x7544fa0>{name = (null), num = }
-- ::59.901 op1[:] --<NSThread: 0x71506f0>{name = (null), num = }
-- ::59.902 op1[:] --<NSThread: 0x7545e60>{name = (null), num = }
设置依赖:
// 设置依赖 ,b2依赖b1,b3依赖b2,所以执行顺序为,b1->b2->b3
[b2 addDependency:b1];
[b3 addDependency:b2];
设置队列的最大并发数量
// 设置最大并发(最多同时并发执行3个任务)
queue.maxConcurrentOperationCount = ;
C、主队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperationWithBlock:^{
NSLog(@"-------%@",[NSThread currentThread]);
// 获取网络图片数据
NSString *str = @"https://ss0.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=3384245408,2851245305&fm=21&gp=0.jpg";
NSURL *url = [NSURL URLWithString:str];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data];
[[NSOperationQueue mainQueue] addOperationWithBlock:^{ // 主队列
NSLog(@"******%@",[NSThread currentThread]);
// 更新界面
[_im1 setImage:image];
}];
}];
最后的结果为:
-- ::16.077 op1[:1c03] -------<NSThread: 0x71613e0>{name = (null), num = }
-- ::17.593 op1[:c07] ******<NSThread: 0x7134fa0>{name = (null), num = } // 主队列
iOS 多线程(NSThread、GCD、NSOperation)的更多相关文章
- iOS多线程 NSThread/GCD/NSOperationQueue
无论是GCD,NSOperationQueue或是NSThread, 都没有线程安全 在需要同步的时候需要使用NSLock或者它的子类进行加锁同步 "] UTF8String], DISPA ...
- [iOS]多线程和GCD
新博客wossoneri.com 进程和线程 进程 是指在系统中正在运行的一个应用程序. 每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内. 比如同时打开QQ.Xcode,系统就会分别 ...
- ios多线程NSThread
1.简介: 1.1 iOS有三种多线程编程的技术,分别是: 1..NSThread 2.Cocoa NSOperation (iOS多线程编程之NSOperation和NSOperationQueue ...
- iOS 多线程学习笔记 —— NSOperation
本文复制.参考自文章:iOS多线程编程之NSOperation和NSOperationQueue的使用 ,主要为了加强个人对知识的理解和记忆,不做他用.原作者声明: 著作权声明:本文由http://b ...
- 多线程 NSThread GCD
ios多线程实现种类 NSThread NSOperationQueue NSObject GCD *************** 1.NSThread //线程 第一种 NSThread *thre ...
- iOS多线程开发之NSOperation - 快上车,没时间解释了!
一.什么是NSOperation? NSOperation是苹果提供的一套多线程解决方案.实际上NSOperation是基于GCD更高一层的封装,但是比GCD更加的面向对象.代码可读性更高.可控性更强 ...
- iOS多线程开发之NSOperation
一.什么是NSOperation? NSOperation是苹果提供的一套多线程解决方案.实际上NSOperation是基于GCD更高一层的封装,但是比GCD更加的面向对象.代码可读性更高.可控性更强 ...
- [转] iOS多线程编程之NSOperation和NSOperationQueue的使用
<iOS多线程编程之NSThread的使用> 介绍三种多线程编程和NSThread的使用,这篇介绍NSOperation的使用. 使用 NSOperation的方式有两种, 一种是用定义好 ...
- iOS多线程编程之NSOperation和NSOperationQueue的使用
前一篇 <iOS多线程编程之NSThread的使用> 介绍三种多线程编程和NSThread的使用,这篇介绍NSOperation的使用. 使用 NSOperation的方式有两种, 一种是 ...
- iOS多线程NSThread和GCD
在iOS中啊 其实有多种方法实现多线程 这里只记录两个比较常用的 或者说我比较常用的 一个就是BSThread 另一个就是一听名字就比较霸气的妇孺皆知的GCD 先说一下NSThread吧 这个方式 ...
随机推荐
- 洛谷P3003 苹果交货Apple Delivery
题目描述 贝西有两个又香又脆的红苹果要送给她的两个朋友.当然她可以走的\(C(1 \leq C \leq 200000)\)条"牛路"都被包含在一种常用的图中,包含了\(P(1 \ ...
- Vue中的指令(听博主说总结的很好)
指令[重点] 作用:简化Dom操作 参考:https://cn.vuejs.org/v2/api/#%E6%8C%87%E4%BB%A4 特点: 1.都是以v-开头 2.除了插值表达式,其它都写在标签 ...
- 如何将拷贝过来的数据 *.ibd 文件生效
1.将拷贝的数据文件 "qqq.idb"放在自己的数据库中. 一般存放在 mysql/ data/ databasename 下 2. "qqq.idb" ...
- Java实现快排+小坑+partition的两种思路
在做一道剑指Offer的题的时候,有道题涉及到快排的思路,一开始就很快根据以前的思路写出了代码,但似乎有些细节不太对劲,自己拿数据试了下果然.然后折腾了下并记录下一些小坑,还有总结下划分方法parti ...
- (转)linux route命令详解
linux route命令详解 原文:https://www.cnblogs.com/lpfuture/p/5857738.html && http://blog.csdn.n ...
- (转)linux自定义开机启动服务和chkconfig使用方法
原文:https://www.cnblogs.com/jimeper/archive/2013/03/12/2955687.html linux自定义开机启动服务和chkconfig使用方法 1. 服 ...
- MvcPager.dll使用实现无刷新分页以及MvcPager的Nuget程序包实现刷新分页
无刷新分页: 1.引入JQuery的NuGet程序包 2.引入程序包 3.引入MvcPager.dll ,MvcPager.dll文件下载链接http://pan.baidu.com/s/1hsvB ...
- iOS 本地缓存实现 方案借鉴
在手机应用程序开发中,为了减少与服务端的交互次数,加快用户的响应速度,一般都会在iOS设备中加一个缓存的机制,前面一篇文章介绍了iOS设备的内存缓存,这篇文章将设计一个本地缓存的机制. 功能需求 这个 ...
- 在java.ext.dirs中使用环境变量导致crontab执行不成功的问题及解决
在java.ext.dirs中使用环境变量导致crontab执行不成功的问题及解决 Table of Contents 1. java.ext.dirs的使用和环境变量 2. 问题:在crontab中 ...
- 解决IE8的兼容问题
本文分享下我在项目中积累的IE8+兼容性问题的解决方法.根据我的实践经验,如果你在写HTML/CSS时候是按照W3C推荐的方式写的,然后下面的几点都关注过,那么基本上很大一部分IE8+兼容性问题都OK ...