介绍:

NSOperation需要配合NSOperationQueue来实现多线程。因为默认情况下,NSOperation单独使用时系统同步执行操作,并没有开辟新线程的能力,只有配合NSOperationQueue才能实现异步执行。

NSOperation是一个抽象类,并不具备封装操作的能力,必须使用它的子类;

因为NSOperation是基于GCD的,那么使用起来也和GCD差不多,其中,NSOperation相当于GCD中的任务,而NSOperationQueue则相当于GCD中的队列。NSOperation实现多线程的使用步骤分为三步:

a. 创建任务:先将需要执行的操作封装到一个NSOperation对象中。

b. 创建队列:创建NSOperationQueue对象。

c. 将任务加入到队列中:然后将NSOperation对象添加到NSOperationQueue中。

之后呢,系统就会自动将NSOperationQueue中的NSOperation取出来,在新线程中执行操作。


NSOperation是个抽象类,并不能封装任务。我们只有使用它的子类来封装任务。我们有三种方式来封装任务。

使用子类NSInvocationOperation
使用子类NSBlockOperation
定义继承自NSOperation的子类,通过实现内部相应的方法来封装任务。
在不使用NSOperationQueue,单独使用NSOperation的情况下系统同步执行操作,下面我们学习以下任务的三种创建方式。

NSInvocationOperation

OC版

 - (void)testB {
// 创建NSInvocationOperation对象
NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil]; // 调用start方法开始执行操作
[op start];
} - (void)run
{
NSLog(@"当前的线程为--%@", [NSThread currentThread]);
}

结果:

2018-01-30 18:46:59.139360+0800 RAC[21774:638747] 当前的线程为--<NSThread: 0x60c000070c00>{number = 1, name = main}

BlockOperation:

Swift 版

只要BlockOperation封装的操作数 > 1,就会异步执行操作,但是不会无限制的创建线程

let blockOpe = BlockOperation()
blockOpe.queuePriority = .veryHigh
blockOpe.addExecutionBlock {
print("BlockOperation执行了",Thread.current)
}
blockOpe.addExecutionBlock {
print("BlockOperation2执行了",Thread.current)
}
blockOpe.start() //开始执行
//blockOpe.cancel() //取消

结果:

OC 版

     NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{

         NSLog(@"-当前的线程为-%@",[NSThread currentThread]);
}]; [op start];

结果:

在没有使用NSOperationQueue、单独使用NSBlockOperation的情况下,NSBlockOperation也是在主线程执行操作,并没有开启新线程。

addExecutionBlock

 NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
// 在主线程
NSLog(@"线程1------%@", [NSThread currentThread]);
}]; // 添加额外的任务(在子线程执行)
[op addExecutionBlock:^{
NSLog(@"线程2------%@", [NSThread currentThread]);
}];
[op addExecutionBlock:^{
NSLog(@"线程3------%@", [NSThread currentThread]);
}];
[op addExecutionBlock:^{
NSLog(@"线程4------%@", [NSThread currentThread]);
}]; [op start];

结果:

blockOperationWithBlock:方法中的操作是在主线程中执行的,而addExecutionBlock:方法中的操作是在其他线程中执行的


NSOperationQueue

和GCD中的并发队列、串行队列略有不同的是:NSOperationQueue一共有两种队列:主队列、其他队列。其中其他队列同时包含了串行、并发功能。

创建队列

主队列

获取主队列以及添加操作到队列,主队列是串行队列,无论是否设置最大并行数量都是在当前线程执行,不会创建新的线程

凡是添加到主队列中的任务(NSOperation),都会放到主线程中执行。

    let queue = OperationQueue.main
queue.addOperation {
for _ in ...{
print("OperationQueue1执行了",Thread.current)
}
}

结果:

其他队列

添加到这种队列中的任务(NSOperation),就会自动放到子线程中执行。同时包含了:串行、并发功能

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

a.

将任务加入到队列中

同时具备串行和并发的功能,默认情况下是并发的,可以手动设置为串行队列,通过设置最大并发数属性来更改

 c func racsTest() {
let queue = OperationQueue()
queue.maxConcurrentOperationCount =
queue.addOperation {
for _ in ...{
print("OperationQueue1执行了",Thread.current)
}
}
//addOperation已经在内部执行了start方法了

结果:


最大并发数

a. 取消队列中的所有任务,除了正在执行的任务,一旦被取消,就不能回复之前的操作。

b. 将最大操作数的值设置为1,可以实现任务的串行效果,但是要注意的是,并不是只开一条子线程(通常会开两条子线程,循环回收复用)

c. 最大并发数6以内,不要开太多,因为虽然任务是在子线程进行处理的,但是cpu处理这些过多的子线程可能会影响UI,让UI卡顿。

 queue.maxConcurrentOperationCount=;

队列的取消

当前正在处于执行状态的任务是不能够取消的,只能取消等待的任务

 queue.cancelAllOperations()

队列的挂起和恢复

当前正在处于执行状态的任务是不能够暂停的,只能暂停等待的任务

 queue.isSuspended = true    //暂停队列
queue.isSuspended = false //恢复队列

等待Options完成

如果需要在当前线程中处理operation完成后的结果,可以使用NSOperation的waitUntilFinished方法阻塞当前线程,等待operation完成

 [operation waitUntilFinished];

使用NSOperationQueue的waitUntilAllOperationsAreFinished方法

 // 阻塞当前线程,等待queue的所有操作执行完毕
[queue waitUntilAllOperationsAreFinished];

添加NSOperation的依赖对象

当某个NSOperation对象依赖于其它NSOperation对象的完成时,就可以通过addDependency方法添加一个或者多个依赖的对象,只有所有依赖的对象都已经完成操作,当前NSOperation对象才会开始执行操作。另外,通过removeDependency方法来删除依赖对象。
 
 let queue = OperationQueue()
//设置依赖关系
let blockOpe1 = BlockOperation()
blockOpe1.addExecutionBlock {
print("blockOpe1执行了")
}
let blockOpe2 = BlockOperation()
blockOpe2.addExecutionBlock {
print("blockOpe2执行了")
}
blockOpe1.addDependency(blockOpe2)
queue.addOperation(blockOpe1)
queue.addOperation(blockOpe2)
// 可以看出,先执行blockOpe2,再执行blockOpe1

结果:


修改Operations的执行顺序

默认所有operation都拥有“普通”优先级,不过可以通过setQueuePriority:方法来提升或降低operation对象的优先级。

         let queue = OperationQueue()
queue.maxConcurrentOperationCount = let blockOpe = BlockOperation()
blockOpe.addExecutionBlock {
print("blockOpe------------>执行了")
}
blockOpe.queuePriority = .veryHigh let blockOpe1 = BlockOperation()
blockOpe1.addExecutionBlock {
print("blockOpe1------------>执行了")
}
blockOpe1.queuePriority = .low queue.addOperation(blockOpe1)
queue.addOperation(blockOpe)

结果:


定义NSOperation的子类

 //    定义一个继承自NSOperation的子类,重写main方法
// YSCOperation.h
#import <Foundation/Foundation.h> @interface YSCOperation : NSOperation @end // YSCOperation.m #import "YSCOperation.h" @implementation YSCOperation
/**
* 需要执行的任务
*/ - (void)main
{
for (int i = ; i < ; ++i) {
NSLog(@"--i---%@",[NSThread currentThread]);
}
} @end // 导入头文件YSCOperation.h
// 创建YSCOperation
YSCOperation *op1 = [[YSCOperation alloc] init]; [op1 start];

结果:

--0---<NSThread: 0x6080000779c0>{number = 1, name = main}
--1---<NSThread: 0x6080000779c0>{number = 1, name = main}

在没有使用NSOperationQueue、单独使用自定义子类的情况下,是在主线程执行操作,并没有开启新线程。

Operation(Swift)的更多相关文章

  1. iOS四种多线程(swift和oc)

    在这篇文章中,我将为你整理一下 iOS 开发中几种多线程方案,以及其使用方法和注意事项.当然也会给出几种多线程的案例,在实际使用中感受它们的区别.还有一点需要说明的是,这篇文章将会使用 Swift 和 ...

  2. iOS多线程学习

    在 iOS 中其实目前有 4 套多线程方案,他们分别是: Pthreads NSThread GCD NSOperation & NSOperationQueue 所以接下来,我会一一讲解这些 ...

  3. iOS多线程

    关于iOS多线程 概述 这篇文章中,我不会说多线程是什么.线程和进程的区别.多线程有什么用,当然我也不会说什么是串行.什么是并行等问题,这些我们应该都知道的. 在 iOS 中其实目前有 4 套多线程方 ...

  4. iOS多线程解析

    在这篇文章中,我将为你整理一下 iOS 开发中几种多线程方案,以及其使用方法和注意事项.当然也会给出几种多线程的案例,在实际使用中感受它们的区别.还有一点需要说明的是,这篇文章将会使用 Swift 和 ...

  5. 关于iOS多线程的总结

    关于iOS多线程的总结   在这篇文章中,我将为你整理一下 iOS 开发中几种多线程方案,以及其使用方法和注意事项.当然也会给出几种多线程的案例,在实际使用中感受它们的区别.还有一点需要说明的是,这篇 ...

  6. 关于iOS多线程,你看我就够了

    在这篇文章中,我将为你整理一下 iOS 开发中几种多线程方案,以及其使用方法和注意事项.当然也会给出几种多线程的案例,在实际使用中感受它们的区别.还有一点需要说明的是,这篇文章将会使 用 Swift  ...

  7. IOS多线程处理

    http://www.jianshu.com/p/0b0d9b1f1f19 首页专题下载手机应用 显示模式登录     注册登录 添加关注 作者 伯恩的遗产2015.07.29 00:37* 写了35 ...

  8. iOS多线程(转)

    关于iOS多线程,你看我就够了 字数8596 阅读28558 评论74 喜欢313 在这篇文章中,我将为你整理一下 iOS 开发中几种多线程方案,以及其使用方法和注意事项.当然也会给出几种多线程的案例 ...

  9. iOS多线程方案总结及使用详解

    本篇文章整理了几种iOS中主要的多线程方案,提供了Swift和Objective-C两种语言的写法. 概述 iOS目前有四种多线程解决方案: NSThread GCD NSOperation Pthr ...

随机推荐

  1. HBase系列文章(转)

    HBase概念学习(一)基本架构 HBase概念学习(二)JAVA API操作概览 HBase概念学习(三)Java API之CRUD(增查改删) HBase概念学习(四)Java API之扫描和过滤 ...

  2. mysql大表更新sql的优化策略(转)

    看了该文章之后,很受启发,mysql在update时,一般也是先select.但注意,在Read Committed隔离级别下,如果没有使用索引,并不会锁住整个表, 还是只锁住满足查询条件的记录而已. ...

  3. c#中base64编码解码

    //编码: byte[] bytes = Encoding.Default.GetBytes("要转换的字符"); string str = Convert.ToBase64Str ...

  4. zabbix监控托管主机遇到问题

    昨天监控公司的托管主机时发现监控不上,回想起来其实就是个小问题,分分钟能解决的事,排错的过程才是真正耗心费神的. 监控环境: A zabbix server: 192.168.17.110 serve ...

  5. oracle用户被锁

    使用PLSQL客户端:1.用管理员账户登录PLSQL Developer(登录名可以为system,选择类型的时候把Normal修改为Sysdba).2.左侧选择My Objects,查看Users文 ...

  6. cors与jsonp

    在.net中,可以在webApiConfig代码里写,也可以在web.config里配置,但都需要引入System.Web.Cors.这些都是服务器端的配置,对整个项目有效. {若只想对某个请求有效, ...

  7. RN animated帧动画

    效果图: 代码: export default class AnimationFrameScene extends Component { constructor () { super() this. ...

  8. 20170927 Webservice发布指定账户进行访问

    1. 搭建IIS 平台 于服务器A1 2.发布Webservice 到A1 我的问题在于(Webservice中方法中内容会对B1服务器的共享路径进行写入文件动作), 如何来控制网页使用特定的账户去访 ...

  9. 怎样使用EOS.JS的API

    https://medium.com/coinmonks/how-to-use-eosjs-api-1-770b037b22ad https://blog.csdn.net/mongo_node/ar ...

  10. Python 命名笔记

    类名开头大写,驼峰命名 函数名,变量名都小写, 全局常量 如COUNT, 使用全部大写 https://www.cnblogs.com/lytwajue/p/7324724.html 这个是全局变量关 ...