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吧 这个方式 ...
随机推荐
- 如何将拷贝过来的数据 *.ibd 文件生效
1.将拷贝的数据文件 "qqq.idb"放在自己的数据库中. 一般存放在 mysql/ data/ databasename 下 2. "qqq.idb" ...
- java监听器原理理解与实现
监听器模型涉及以下三个对象,模型图如下: (1)事件:用户对组件的一个操作,称之为一个事件(2)事件源:发生事件的组件就是事件源(3)事件监听器(处理器):监听并负责处理事件的方法 执行顺序如下: 1 ...
- E. Beautiful Subarrays 字典树
http://codeforces.com/contest/665/problem/E 给定一个序列,问其中有多少个区间,所有数字异或起来 >= k 看到异或,就应该想到异或的性质,A^B^B ...
- (转)vimdiff 快速比较和合并少量文件
vimdiff 快速比较和合并少量文件 原文:http://www.cnblogs.com/abeen/p/4255754.html 纯文本文件比较和合并工具一直是软件开发过程中比较重要的组成部分,v ...
- PHP面向对象编程一
php面向对象编程(一) 类与对象关系: 类就像一个人类的群体 我们从类中实例化一个对象 就像是制定一个人. 面向对象程序的单位就是对象,但对象又是通过类的实例化出来的,所以我们首先要做的就是如何 ...
- linux下的tomcat开机自启动(亲测),更改静态ip
开机自启动Tomcat: 1.修改脚本文件rc.local:vim /etc/rc.d/rc.local 这个脚本是使用者自定的开机启动程序,可以在里面添加想在系统启动之后执行的脚本或者脚本执行命令 ...
- nodejs入门学习笔记二——解决阻塞问题
在最开始,我们要弄清楚node会什么会存在阻塞? node是这么标榜自己的:“在node中除了代码,所有一切都是并行执行的!” 意思是,Node.js可以在不新增额外线程的情况下,依然可以对任务进行并 ...
- Django之model基础(增删改查)
一.ORM 映射关系 表名 <-------> 类名 字段 <-------> 属性 表记录 <------->类实例对象二.创建表(建立模型) 在创建表之前的准备 ...
- table-列组
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- python3基础07(进程操作及执行系统级命令等)
#subprocess 创建子进程 连接输入 输出 管道错误,及获取他们的状态,可执行操作系统级的命令# subprocess.run(args, *, stdin=None, input=None, ...