NSOperation简介

1.实现多线程编程步骤:

配合使用NSOperation和NSOperationQueue实现多线程编程,我们不用考虑线程的生命周期、同步、加锁等问题,如下:

  • 先将需要执行的操作封装到一个NSOperation对象中
  • 然后将NSOperation对象添加到NSOperationQueue中
  • 系统会自动将NSOperation中封装的操作放到一条新线程中执行

2.NSOperation的子类:

NSOperation是个抽象类,并不具备封装操作的能力,必须使⽤它的子类,使用NSOperation⼦类的方式有3种:

  • NSInvocationOperation
  • NSBlockOperation
  • 自定义子类继承NSOperation,实现内部相应的⽅法

封装操作到NSOperation对象中(步骤一)

1.NSInvocationOperation

- (void)invocationOperation {

    //封装操作(任务)
//注意:默认情况下,调用了start方法后并不会开一条新线程去执行操作,而是在当前线程同步执行操作。只有将operation放到一个NSOperationQueue中,才会异步执行操作
NSInvocationOperation *op1 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(startExecute:) object:@"funky"];
[op1 start];
} - (void)startExecute:(NSString *)param { NSLog(@"-------线程:%@ ------ 参数:%@",[NSThread currentThread],param);
//执行操作...
}

NSInvocationOperation封装操作

2.NSBlockOperation

- (void)blockOperation {

    //注意:如果一个操作中的任务数量大于1,那么会开子线程并发执行任务,但不一定是子线程,有可能是主线程

    NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"----- %@",[NSThread currentThread]);
//执行操作...
}]; NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"----- %@",[NSThread currentThread]);
//执行操作...
}]; [op1 addExecutionBlock:^{
//op1追加任务1...
}];
[op1 addExecutionBlock:^{
//op1追加任务2...
}]; [op start];
[op1 start];
}

NSBlockOperation封装及追加任务

添加到NSOperationQueue中(步骤二)

1.NSInvocationOperation对象添加到NSOperationQueue中

- (void)invocationOperationWithQueue {

    //1.封装操作(任务)
NSInvocationOperation *op1 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(startExecute:) object:@"funky"]; //2.创建队列(主队列,非主队列)
//主队列 : [NSOperationQueue mainQueue]; (同GCD的主队列,串行队列)
//非主队列 : [[NSOperationQueue alloc]init]; (同时具备并发和串行的功能,默认是并发队列)
NSOperationQueue *queue = [[NSOperationQueue alloc]init]; //3.把操作添加到队列中 (内部已经调用了 [op1 start])
[queue addOperation:op1]; } - (void)startExecute:(NSString *)param { NSLog(@"-------线程:%@ ------ 参数:%@",[NSThread currentThread],param);
//执行操作...
}

2.NSBlockOperation对象添加到NSOperationQueue中及简便方式

- (void)blockOperationWithQueue {

    NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"----- %@",[NSThread currentThread]);
//执行操作...
}]; NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"----- %@",[NSThread currentThread]);
//执行操作...
}]; //创建队列
NSOperationQueue *queue = [[NSOperationQueue alloc]init]; //添加到队列中
[queue addOperation:op];
[queue addOperation:op1]; } //或简便方法
-(void)simpleWay{
//创建队列
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
[queue addOperationWithBlock:^{
NSLog(@"开子线程执行任务----%@",[NSThread currentThread]);
}]; }

3.自定义子类继承NSOperation

#import "CustomOperation.h"

@implementation CustomOperation

//重写main方法,在main方法中 执行操作
//可以提高代码复用性
-(void)main { NSLog(@"----- %@",[NSThread mainThread]); } @end

继承于NSOperation的自定义类.m

- (void)customOperationWithQueue {

    CustomOperation *op = [[CustomOperation alloc]init];
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
[queue addOperation:op];
}

使用CustomOperation

NSOperation的其他用法

1.NSOperation系统的子类的取消,暂定操作

//开始执行任务
- (IBAction)startBtnClick:(UIButton *)sender { self.queue = [[NSOperationQueue alloc]init]; //maxConcurrentOperationCount 最大并发数(同一时间最多有多少条任务可以执行)
// >1并发队列 =1串行队列 =0不执行任务 =-1默认,代表最大值,最大并发数不受限制
self.queue.maxConcurrentOperationCount = ; NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{ for (int i =; i < ; i++) {
NSLog(@"download1-----%@",[NSThread currentThread]);
} }]; NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{ for (int i =; i < ; i++) {
NSLog(@"download2-----%@",[NSThread currentThread]);
} }]; NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{ for (int i =; i < ; i++) {
NSLog(@"download3-----%@",[NSThread currentThread]);
} }]; [self.queue addOperation:op1];
[self.queue addOperation:op2];
[self.queue addOperation:op3]; }
//暂停执行任务
- (IBAction)stopBtnClick:(UIButton *)sender { //可恢复,不能暂停当前正处于执行状态的任务
[self.queue setSuspended:YES];
}
//继续执行任务
- (IBAction)goOnBtnClick:(UIButton *)sender { [self.queue setSuspended:NO];
}
//取消执行任务
- (IBAction)cancelBtnClick:(UIButton *)sender { //不可恢复
//该方法内部调用了所有operation的cancel方法
[self.queue cancelAllOperations];
}

2.自定义NSOperation的取消操作

//开始执行任务
- (IBAction)startBtnClick:(UIButton *)sender { self.queue = [[NSOperationQueue alloc]init]; self.queue.maxConcurrentOperationCount = ; HSOperation *op = [[HSOperation alloc]init]; [self.queue addOperation:op]; }
//取消执行任务
- (IBAction)cancelBtnClick:(UIButton *)sender { //不可恢复
//该方法内部调用了所有operation的cancel方法
[self.queue cancelAllOperations];
}
#import "HSOperation.h"

@implementation HSOperation

-(void)main {

    //3个耗时操作,但相当于一个任务
for (int i =; i < ; i++) { //if (self.isCancelled) return; 写在这会耗费性能,不建议在这进行操作
NSLog(@"download1-----%@",[NSThread currentThread]);
} //检测是否取消了操作
if (self.isCancelled) return; for (int i =; i < ; i++) {
NSLog(@"download2-----%@",[NSThread currentThread]);
} if (self.isCancelled) return; for (int i =; i < ; i++) {
NSLog(@"download3-----%@",[NSThread currentThread]);
} } @end

HSOperation.m

3.操作依赖及操作监听

-(void)addDependency{

    NSOperationQueue *queue = [[NSOperationQueue alloc]init];

    NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{

        //耗时操作1...
NSLog(@"download1-----%@",[NSThread currentThread]); }]; NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{ //耗时操作2...
NSLog(@"download2-----%@",[NSThread currentThread]); }]; NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{ //耗时操作3...
NSLog(@"download3-----%@",[NSThread currentThread]); }]; NSBlockOperation *op4 = [NSBlockOperation blockOperationWithBlock:^{ //耗时操作4...
NSLog(@"download4-----%@",[NSThread currentThread]); }]; //操作监听
op3.completionBlock = ^{ NSLog(@"download3下载完成了-----%@",[NSThread currentThread]); }; //操作依赖
[op1 addDependency:op2]; //op1 等待 op2执行后 在执行
[op2 addDependency:op4];
[op4 addDependency:op3];
// [op3 addDependency:op1]; 不能循环依赖 [queue addOperation:op1];
[queue addOperation:op2];
[queue addOperation:op3];
[queue addOperation:op4]; }

NSOperation线程间的通信

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

    NSOperationQueue *queue = [[NSOperationQueue alloc]init];

    NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{

        NSURL *url = [NSURL URLWithString:@"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1490335106967&di=7daac700f5a1425d58131134228ea9bc&imgtype=0&src=http%3A%2F%2Fsh.sinaimg.cn%2Fcr%2F2013%2F1204%2F533155851.jpg"];
NSData *imgData = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:imgData];
NSLog(@"download---%@",[NSThread currentThread]); //回到主线程刷新UI
[[NSOperationQueue mainQueue] addOperationWithBlock:^{ self.imageView.image = image;
NSLog(@"UI---%@",[NSThread currentThread]); }]; }]; [queue addOperation:op]; }


iOS开发 - 多线程实现方案之NSOperation篇的更多相关文章

  1. iOS开发 - 多线程实现方案之Pthread篇

    pthread基础 pthread是POSIX thread的简写,一套通用的多线程API,适用于Unix.Linux.Windows等系统,跨平台.可移植,使用难度大,C语言框架,线程生命周期由程序 ...

  2. iOS开发 - 多线程实现方案之GCD篇

    GCD概念 GCD为Grand Central Dispatch的缩写,纯c语言编写,是Apple开发的一个多核编程的较新的解决方法.它主要用于优化应用程序以支持多核处理器以及其他对称多处理系统.它是 ...

  3. iOS开发 - 多线程实现方案之NSThread篇

    NSThread API //类方法:创建一个线程 + (void)detachNewThreadWithBlock:(void (^)(void))block API_AVAILABLE(macos ...

  4. iOS开发多线程--技术方案

    pthread 实现多线程操作 代码实现: void * run(void *param) {    for (NSInteger i = 0; i < 1000; i++) {         ...

  5. iOS开发多线程篇—NSOperation简单介绍

    iOS开发多线程篇—NSOperation简单介绍 一.NSOperation简介 1.简单说明 NSOperation的作⽤:配合使用NSOperation和NSOperationQueue也能实现 ...

  6. iOS开发多线程篇—NSOperation基本操作

    iOS开发多线程篇—NSOperation基本操作 一.并发数 (1)并发数:同时执⾏行的任务数.比如,同时开3个线程执行3个任务,并发数就是3 (2)最大并发数:同一时间最多只能执行的任务的个数. ...

  7. iOS开发多线程篇—自定义NSOperation

    iOS开发多线程篇—自定义NSOperation 一.实现一个简单的tableView显示效果 实现效果展示: 代码示例(使用以前在主控制器中进行业务处理的方式) 1.新建一个项目,让控制器继承自UI ...

  8. iOS开发多线程篇 09 —NSOperation简单介绍

    iOS开发多线程篇—NSOperation简单介绍 一.NSOperation简介 1.简单说明 NSOperation的作⽤:配合使用NSOperation和NSOperationQueue也能实现 ...

  9. iOS开发多线程篇 11 —自定义NSOperation

    iOS开发多线程篇—自定义NSOperation 一.实现一个简单的tableView显示效果 实现效果展示: 代码示例(使用以前在主控制器中进行业务处理的方式) 1.新建一个项目,让控制器继承自UI ...

随机推荐

  1. int 转十六进制

    //使用1字节就可以表示bpublic static String numToHex8(int b) {        return String.format("%02x", b ...

  2. ThinkPHP RBAC权限管理机制

    RBAC是ThinkPHP很好用的后台权限管理的,话不多说,实现方法如下,也方便以后自己查询使用: 1.新建4个数据库表 self_role权限表 CREATE TABLE `self_role` ( ...

  3. 管中窥Vue

    博客文章链接:管中窥Vue Vue和Angular.React.js的相同点和不同点? 与React的相同: 都使用了Virtual DOM 提供了响应式和组件化的视图组件 将注意力集中保持在核心库, ...

  4. ps 工具栏使用

    1:称动工具,快捷键是v,则选中移动工具:按shift和左键,可移动当前层移到另一层的中间对齐.如果不用sfhift键,则只是移动:alt+左键上移动,则复制层:alt+中间滚轮,则为放大和缩小. 2 ...

  5. SDUT OJ 2088 refresh的停车场

    refresh的停车场 Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述  refresh最近发了一笔横财,开了一家停车场.由于土地 ...

  6. hdu1198 Farm Irrigation —— dfs or 并查集

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1198 dfs: #include<cstdio>//hdu1198 dfs #includ ...

  7. 人生苦短之Python类的一二三

    在Python中,类也是以class开头定义的.我们定义一个动物类,它有名字和年龄,在java变量有实例变量和局部变量,方法内的变量是局部变量,类里面的变量是实例变量.那么在Python中的类及其属性 ...

  8. 基于BASYS2的VHDL程序——数字钟

    在编电子表时发现FPGA求余,取模只能针对2的次方.毕竟是数字的嘛! 时钟用到了动态刷新数码管.以一个大于50Hz的速度刷新每一个数码管. 因为数码管只有四个,只写了分针和秒针. 代码如下: libr ...

  9. Lucene小例子

    package org.itat.test; import java.io.File; import java.io.FileReader; import java.io.IOException; i ...

  10. Spring cloud基础模块学习

    1.微服务架构构成 单体架构(通过应用集群和数据库集群来提高性能,多余模块存在浪费) 垂直架构(新的功能模块通过新项目来实现,数据库之间存在交叉关联.存在数据冗余,和单体架构一样通过扩展集群结点,成本 ...