iOS-多线程之NSOperation
前言
这篇文章主要讲NSOperation的使用。
What
使用NSOperation和NSOperationQueue进行多线程开发类似于线程池,只要将一个NSOperation(实际开发中需要使用其子类NSInvocationOperation、NSBlockOperation)放到NSOperationQueue这个队列中线程就会依次启动。NSOperationQueue负责管理、执行所有的NSOperation,在这个过程中
可以更加容易管理线程总数和控制线程之间的依赖关系。NSOperation 利用他来创建线程操作,线程操作只有放在线程队列中才会在子线程中执行。
NSOperationQueue: 线程队列分两种类型。
- 主队列
- [NSOperationQueue mainQueue]
- 凡是添加到主队列中的任务(NSOperation),都会放到主线程中执行。
- 非主队列
- [[NSOperationQueue alloc]init]
- 添加到这种队列中的任务,都会放到子线程中执行。
NSOperation常用子类用于创建线程操作:NSInvocationOperation和NSBlockOperation,两种方式本质没有区别,但后者使用block形式进行代码组织,使用相对方便。也可以用自定义的继承于NSOperation的类来创建线程操作。
- 主队列
How
配合使用NSOperation和NSOperationQueue实现多线程编程,一共有三种方式,但其实这三种方式都是采用NSOperation的子类与NSOperationQueue搭配实现多线程开发。这三个子类分别是NSInvocationOperation、NSBlockOperation和自定义继承于NSOperation的类,前两者是系统提供的子类。
方式一 NSInvocationOperation与NSOperationQueue搭配
创建一个线程操作,并实现方法选择器选择的方法
//创建一个线程操作 NSInvocationOperation *invocationOperation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(invocationOperation:) object:kurl]; //让线程操作开始执行。但是如果这样做的话这个操作将会在主线程中执行,只有将这个操作放进队列,才会开辟一个子线程让这个操作在子线程中执行。 //[invocationOperation start];创建一个线程队列
NSOperationQueue *operationQueue = [NSOperationQueue new];将创建好的线程操作放在线程队列中
//只有放在线程队列中的线程操作才会在子线程中执行。线程队列负责管理、执行所有的NSOperation [operationQueue addOperation:invocationOperation];在创建线程操作时选择的方法内更新UI
- (void)invocationOperation:(NSString *)url{ //虽然没有采用NSThread创建线程,但仍可以使用[NSThread currentThread]来获取当前的线程。 NSLog(@"invocationOperation方法所在的线程%@",[NSThread currentThread]); NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:kurl]]; //在子线程中回到主线程更新UI [[NSOperationQueue mainQueue] addOperationWithBlock:^{ imageView.image = [UIImage imageWithData:data]; }]; }到目前为止是不是感觉跟NSThread挺相似的,接下来简单分析一下两者的区别。
NSThread需要启动,也就是说需要费心管理声明周期,而采用Operation只需将线程操作放到线程队列中即可,线程队列负责管理、执行所有的NSOperation。
管理线程的最大并发数,也就是同时执行的任务数。
//默认是-1,不能设为0,如果设置为0就不执行任务。 operationQueue.maxConcurrentOperationCount = 1;控制线程之间的依赖关系,NSOperation之间可以设置依赖来保证执行顺序,比如一定要让操作1执行完后,才能执行操作2。线程之间不能相互依赖,不如A依赖于B,B有依赖于A。
//操作1依赖于操作2 [invocationOperation1 addDependency:invocationOperation2];队列的取消、暂停、恢复
只要设置队列的suspended为YES, 那么就会暂停队列中其它任务的执行,也就是说不会再继续执行没有执行到得任务
self.queue.suspended = YES;注意: 设置为暂停之后, 不会立即暂停,会继续执行当前正在执行的任务, 直到当前任务执行完毕, 就不会执行下一个任务了,也就是说, 暂停其实是暂停下一个任务, 而不能暂停当前任务
注意: 暂停是可以恢复的,只要设置队列的suspended为NO, 那么就会恢复队列中其它任务的执行
取消队列中所有的任务的执行
[self.queue cancelAllOperations];取消和暂停一样, 是取消后面的任务, 不能取消当前正在执行的任务,取消是不可以恢复的
方式二 NSBlockOperation与NSOperationQueue搭配,其实方式一和方式二没有什么本质区别。主要是后者使用block形式进行代码组织,使用相对方便。
- (void)viewDidLoad{ [super viewDidLoad]; imageView = [[UIImageView alloc]initWithFrame:CGRectMake(50, 50, 200, 200)]; [self.view addSubview:imageView]; //1. 创建线程操作 NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"blockOperation线程操作所在的线程%@",[NSThread currentThread]); NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:kurl]]; [[NSOperationQueue mainQueue] addOperationWithBlock:^{ NSLog(@"更新UI所在的线程%@",[NSThread currentThread]); imageView.image = [UIImage imageWithData:data]; }]; }]; //2. 创建线程队列 NSOperationQueue *operationQueue = [NSOperationQueue new]; //3. 将线程操作放到线程队列中 [operationQueue addOperation:blockOperation]; //PS: 简化以上操作 //1. 创建一个线程队列 NSOperationQueue *operationQueue = [NSOperationQueue new]; //直接利用线程队列的addOperationWithBlock添加线程操作。 [operationQueue addOperationWithBlock:^{ NSLog(@"更新UI所在的线程%@",[NSThread currentThread]); }]; }方式三 继承于NSOperation的子类与NSOperationQueue的搭配
创建一个继承于NSOperation的类,并在.m文件中重写main方法,main方法便是该线程要执行的操作。注意,如果是同步操作,该方法能够自动访问到主线程的自动释放池,如果是异步执行操作,那么将无法访问到主线程的自动释放池,需要再main中再新建一个自动释放池,来帮助管理内存。
创建线程队列,并把线程操作放在线程队列中。
.h
// // CoustomOperation.h // NSOperation // // Created by GG on 16/2/26. // Copyright © 2016年 GG. All rights reserved. // #import <Foundation/Foundation.h> #import <UIKit/UIKit.h> @interface CoustomOperation : NSOperation //接收传进来的图片对象 @property (nonatomic,retain) UIImageView *imageView; //在该该类对象初始化时,将图片试图对象传到类中。 - (instancetype)initWithImageView:(UIImageView *)imageView; @end.m
// // CoustomOperation.m // NSOperation // // Created by GG on 16/2/26. // Copyright © 2016年 GG. All rights reserved. // #import "CoustomOperation.h" #define kurl @"http://store.storeimages.cdn-apple.com/8748/as-images.apple.com/is/image/AppleInc/aos/published/images/s/38/s38ga/rdgd/s38ga-rdgd-sel-201601?wid=848&hei=848&fmt=jpeg&qlt=80&op_sharpen=0&resMode=bicub&op_usm=0.5,0.5,0,0&iccEmbed=0&layer=comp&.v=1454777389943" @implementation CoustomOperation - (instancetype)initWithImageView:(UIImageView *)imageView { self = [super init]; if (self) { self.imageView = imageView; } return self; } - (void)main{ //新建一个自动释放池,因为如果是同步操作,该方法能够自动访问到主线程的自动释放池,如果是异步执行操作,那么将无法访问到主线程的自动释放池。 @autoreleasepool { NSLog(@"获取图片所在的线程%@",[NSThread currentThread]); NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:kurl]]; [[NSOperationQueue mainQueue] addOperationWithBlock:^{ NSLog(@"更新UI所在的线程%@",[NSThread currentThread]); self.imageView.image = [UIImage imageWithData:imageData]; }]; } } @endViewController.m
- (void)viewDidLoad{ [super viewDidLoad]; imageView = [[UIImageView alloc]initWithFrame:CGRectMake(50, 50, 200, 200)]; [self.view addSubview:imageView]; CoustomOperation *coustomOperation = [[CoustomOperation alloc] initWithImageView:(UIImageView *)imageView]; NSOperationQueue *operationQueue = [NSOperationQueue new]; // [operationQueue addOperation:coustomOperation]; }
总结: 这三种方式中,感觉方式一是最麻烦的,方式二相对而已简洁不少,而方式三更适合于封装某一个线程操作。
iOS-多线程之NSOperation的更多相关文章
- iOS多线程之NSOperation详解
使用NSOperation和NSOperationQueue进行多线程开发,只要将一个NSOperation(实际开发中需要使用其子类 NSInvocationOperation,NSBlockOpe ...
- iOS 多线程之NSOperation篇举例详解
这篇博客是接着总篇iOS GCD NSOperation NSThread等多线程各种举例详解写的一个支篇.总篇也包含了此文的链接.本文讲解的知识点有NSBlockOperationClick,队列, ...
- IOS多线程之NSOperation学习总结
NSOperation简介 1.NSOperation的作用 配合使用NSOperation和NSOperationQueue也能实现多线程编程 2.NSOperation和NSOperationQu ...
- iOS多线程之NSOperation,NSOperationQueue
使用 NSOperation的方式有两种, 一种是用定义好的两个子类: NSInvocationOperation 和 NSBlockOperation. 另一种是继承NSOperation 如果你也 ...
- (五十六)iOS多线程之NSOperation
NSOpertation是一套OC的API,是对GCD进行的Cocoa抽象. NSOperation有两种不同类型的队列,主队列和自定义队列. 主队列运行于主线程上,自定义队列在后台运行. [NSBl ...
- iOS多线程之NSOperation和NSOperationQueue的使用
一:NSOperation 两个子类+重写main方法 NSInvocationOperation NSBlockOperation 有个类方法 BlockOprationWith: 还有就是自己个子 ...
- ios多线程之NSOperation
使用 NSOperation的方式有两种, 一种是用定义好的两个子类: NSInvocationOperation 和 NSBlockOperation. 另一种是继承NSOperation 如果你也 ...
- iOS多线程之8.NSOPeration的其他用法
本文主要对NSOPeration的一些重点属性和方法做出介绍,以便大家可以更好的使用NSOPeration. 1.添加依赖 - (void)addDependency:(NSOperation * ...
- iOS多线程之GCD小记
iOS多线程之GCD小记 iOS多线程方案简介 从各种资料中了解到,iOS中目前有4套多线程的方案,分别是下列4中: 1.Pthreads 这是一套可以在很多操作系统上通用的多线程API,是基于C语言 ...
- 多线程之NSOperation
关于多线程会有一系列如下:多线程之概念解析 多线程之pthread, NSThread, NSOperation, GCD 多线程之NSThread 多线程之NSOperation 多线程之GCD
随机推荐
- Entity Framework增删改之通用精简方法
用EF用了好长一段时间了,从EF4.0的版本开始接触,感觉这个ORM不能说性能是最好的,但是我个人感觉功能实现以及和mvc的结合还是一个不错的企业级网站的解决方案,在此写个简易的通用扩展方法来方便大家 ...
- Unity 3D 一个简单的角色控制脚本
之所以写这个脚本,是因为我想起了我还是新手的时候,那时为了一个角色控制脚本百度了半天还是一无所获,因为看不懂啊,都写的太高级了 希望这个脚本能够帮助那些 像曾经的我一样迷失于代码中的新手们能够清晰的理 ...
- jQuery带遮罩层弹窗实现(附源码)
1.CSS样式 <style type="text/css"> body { font:11px/1.6em Microsoft Yahei; background:# ...
- 由node-webkit想到
本人做为.NET的死忠也有些许年头.微软这几年被谷歌苹果之流打的有点招架不住..NET的前景也难免堪忧.虽然我认为就强类型语言方面,C#绝对是最强者.但是新技术的发展确实是可怕的,看看苹果几年就把no ...
- MVC+EF+esayui初试(一 布局加菜单显示)
最近都在做linq+ext.net的开发.这两天想学习下MVC和ef,刚好,在看ext.js的时候也喜欢上了esayui,所以就想用mvc+ef+esayui做一个汽车网后台管理来加强下.在这里也把我 ...
- 使用innerHTML获取HTML代码时,HTML标记属性的双引号好多都消失不见了,原来是属性值中包含空格才会保留双引号
最近搞的一个项目中所使用的方式比较奇怪,用Label显示HTML内容,然后不断地使用JS把Label的innerHTML复制到TextBox中. 但是,昨天发现了一个问题,获取元素值的时候,有时候正常 ...
- 使用C#开发屏幕保护程序步骤
本文介绍使用C#制作屏幕保护的方法,这个屏幕保护就是仿效视窗系统自带的字幕屏保. 屏幕保护程序的扩展名虽然是"scr",但其实是一个可执行的"exe"文件.但他 ...
- 重新想象 Windows 8 Store Apps (54) - 绑定: 增量方式加载数据
[源码下载] 重新想象 Windows 8 Store Apps (54) - 绑定: 增量方式加载数据 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 绑定 通过实 ...
- 重新想象 Windows 8.1 Store Apps 系列文章索引
[源码下载] [重新想象 Windows 8 Store Apps 系列文章] 重新想象 Windows 8.1 Store Apps 系列文章索引 作者:webabcd 1.重新想象 Windows ...
- hadoop pipes wordcount compile
http://devel.cs.stolaf.edu/projects/bw/wiki.real/index.php/Hadoop_Reference,_January_2011 http://guo ...