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吧 这个方式 ...
随机推荐
- 关于cookies,sessionStorage和localStorage的区别
如果我说得啰嗦了,请麻烦提醒我一下~~ 面试的时候说: 首先这三个可以在浏览器端按下F12,在Application可以查看到. 如下图: cookies: sessionStorage: sessi ...
- 前端实现Tab切换栏
tab切换,所需的 UI 只有两组元素 - Header 和 Tab,下面介绍几种不同的实现方法和他们的优缺点 本文主要说一些 CSS 的实现方法.最好的方法是 第四种 => label + i ...
- JavaScript高级程序设计第三版-读书笔记(1-3章)
这是我第一次用markdown,也是我第一次在网上记录我自己的学习过程. 第一章 JavaScript主要由以下三个不同的部分构成 ECMAScript 提供核心语言功能 DOM 提供访问 ...
- 1093 Count PAT's(25 分)
The string APPAPT contains two PAT's as substrings. The first one is formed by the 2nd, the 4th, and ...
- jquery——解决鼠标移入移出导致盒子不停移动的bug
使用mouseover().mouseout()时会出现这样一种情况,鼠标快速多次移入移出后这个盒子会在鼠标不动后继续运动 代码如下: <!DOCTYPE html> <html l ...
- 配置HEXO
软件介绍 Hexo 是一个快速.简洁且高效的博客框架.Hexo 使用 Markdown(或其他渲染引擎)解析文章,在几秒内,即可利用靓丽的主题生成静态网页. 使用版本和操作系统 官网最新版 Windo ...
- arch搭建SVN服务器
一.安装 Install the package Install subversion from the official repositories. Create a repository Crea ...
- PHP session变量的销毁
1.何为session? 相当于一个客户端(可以是浏览器.app.ftp等其他,而且同一个浏览器多开几个又算是不同的客户端)对服务器的一个访问,这个期间服务器为此建立一个唯一的标示(session_i ...
- Mybatis-Plus使用全解
前言 之前写了<SpringBoot | 第九章:Mybatis-plus的集成和使用>一文,只是简单的使用条件构造器列举了一些通用的CURD操作.本人也想写一篇通用的关于mybatis- ...
- JavaFX上手--第1天
1.第一个JavaFX Application JavaFX 使用Java来制作可视化图形,可以做动画和3D效果,JavaFX从JDK中直接使用. package application; impor ...