这篇文章里我将不过多的谈及理论知识,这些东西会的自然会,不会的,看多了也是云里雾里。下面我讲更多的用代码+注释的方式来讲如何使用NSOperation和NSOperationQueue。

  1、NSOperation。是抽象类,不能够直接使用,而是使用子类NSInvocationOperation和NSBlockOperation来实际执行任务。NSOperation本身和多线程是没有任何关系的,她只是封装了一个代码段和数据去实现一个功能。

  1.1、NSInvocationOperation,基于一个对象和selector来创建操作。看下面的代码:

 - (void)invocationOperation {

     NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(startOpration) object:nil];
[operation setCompletionBlock:^{
NSLog(@"执行完成,是否主线程:%@", [NSThread isMainThread] == ? @"YES" : @"NO");
}];
[operation start]; //启动任务
[operation cancel]; //取消任务
[operation isExecuting]; //任务是否在执行
[operation isFinished]; //任务是否已经结束
} - (void)startOpration {
NSLog(@"开始执行,是否主线程:%@", [NSThread isMainThread] == ? @"YES" : @"NO");
}

  首先是创建了一个operation,并给operation添加了一个需要执行的方法:startOpration。其中Line4中的方法将会在operation执行完成后执行,当然不是必须的,如果需要在operation执行完进行一些操作,可以写上这个方法。

  下面是执行的结果:

-- ::19.577 NSOperation[:] 开始执行,是否主线程:YES
-- ::19.577 NSOperation[:] 执行完成,是否主线程:NO

  根据上面执行的结果,我们可以发现, startOpration 这个方法是在主线程执行的。至于Line4~Line6是在子线程执行的,则不在今天的讨论内容中,略过。

  1.2、NSBlockOperation。相对于NSInvocationOperation,NSBlockOperation则是将selector中需要调用的方法使用Block进行了封装,使用起来更加的方便。关于Block的使用,不明白的同学可以参考我的上一篇博客。

  NSBlockOperation对象能够并发的执行一个或多个Block对象,所有相关的Block都执行完成之后,操作才算完成。下面看代码:

 - (void)blockOperation {
//创建一个操作
NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"%d,%@,是否主线程:%@", __LINE__, [NSThread currentThread], [NSThread isMainThread] == ? @"YES" : @"NO");
}];
//通过addExecutionBlock方法添加Block操作
[blockOperation addExecutionBlock:^{
NSLog(@"%d,%@,是否主线程:%@", __LINE__, [NSThread currentThread], [NSThread isMainThread] == ? @"YES" : @"NO");
}];
[blockOperation addExecutionBlock:^{
NSLog(@"%d,%@,是否主线程:%@", __LINE__, [NSThread currentThread], [NSThread isMainThread] == ? @"YES" : @"NO");
}];
[blockOperation addExecutionBlock:^{
NSLog(@"%d,%@,是否主线程:%@", __LINE__, [NSThread currentThread], [NSThread isMainThread] == ? @"YES" : @"NO");
}];
[blockOperation addExecutionBlock:^{
NSLog(@"%d,%@,是否主线程:%@", __LINE__, [NSThread currentThread], [NSThread isMainThread] == ? @"YES" : @"NO");
}];
//执行操作
[blockOperation start];
//上面的几个Block是并发执行的,将会在不同的线程中执行,
}

  下面是执行的结果:

-- ::28.585 NSOperation[:] ,<NSThread: 0x7f97cad07c30>{number = , name = main},是否主线程:YES
-- ::28.585 NSOperation[:] ,<NSThread: 0x7f97cae223c0>{number = , name = (null)},是否主线程:NO
-- ::28.585 NSOperation[:] ,<NSThread: 0x7f97cac0eb60>{number = , name = (null)},是否主线程:NO
-- ::28.586 NSOperation[:] ,<NSThread: 0x7f97cad07c30>{number = , name = main},是否主线程:YES
-- ::28.585 NSOperation[:] ,<NSThread: 0x7f97cad06530>{number = , name = (null)},是否主线程:NO

  可以从上面的执行结果中,很容易的发现,程序是并行的执行。而创建的操作,也就是:Line4是在主线程中执行,而其他通过通过 addExecutionBlock 方法添加的Block操作则是在不同的线程中执行。

  通过上面的说明,我要总结的是:NSOperation以及子类,只是一个操作,本身无主线程和子线程的区分,可以在任意线程中使用。也就是,在主线程中创建的操作将在主线程中执行,在子线程中创建的操作将在子线程中执行。而实现多线程可以配合NSOperationQueue来实现。下面来介绍NSOperationQueue。

  2.NSOperationQueue,是操作队列,它用来管理一组NSOperation对象的执行,会根据需要自动为NSOperation对象开辟适合数量的线程,以完成任务的并行执行。下面上代码:

 - (void)operationQueue {
//创建一个任务队列,alloc(new)出来的任务队列将会在子线程中执行,并且是并发执行
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//创建操作NSInvocationOperation
for (int i = ; i < ; i++) {
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(startOpration) object:nil];
[queue addOperation:operation];
}
//创建NSBlockOperation操作
for (int i = ; i < ; i++) {
NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"%d,%@,%d", __LINE__, [NSThread currentThread], [NSThread isMainThread]);
}];
//将操作添加到队列中
[queue addOperation:blockOperation];
}
//设置最大并发数,当把最大并发数设置1时,此时队列相当于串行执行。
queue.maxConcurrentOperationCount = ;
//添加依赖关系
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"这是任务1,依赖于任务2");
}];
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"这是任务2");
}];
//添加依赖关系
//添加依赖关系时,注意不能添加互相依赖,如A依赖B,B依赖A
[op1 addDependency:op2];
//添加依赖关系必须在任务添加到队列之前设置
[queue addOperation:op1];
[queue addOperation:op2];
//回到主线程的操作
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
NSLog(@"%d,%@,%d", __LINE__, [NSThread currentThread], [NSThread isMainThread]);
}];
}

  下面是执行的结果:

 -- ::11.625 NSOperation[:] 开始执行,是否主线程:NO
-- ::11.625 NSOperation[:] 开始执行,是否主线程:NO
-- ::11.625 NSOperation[:] 开始执行,是否主线程:NO
-- ::11.625 NSOperation[:] 开始执行,是否主线程:NO
-- ::11.625 NSOperation[:] 开始执行,是否主线程:NO
-- ::11.626 NSOperation[:] ,<NSThread: 0x7f852bc099f0>{number = , name = (null)},
-- ::11.627 NSOperation[:] ,<NSThread: 0x7f852bf0db10>{number = , name = (null)},
-- ::11.628 NSOperation[:] ,<NSThread: 0x7f852bc46ee0>{number = , name = (null)},
-- ::11.628 NSOperation[:] ,<NSThread: 0x7f852bc4fe00>{number = , name = (null)},
-- ::11.628 NSOperation[:] ,<NSThread: 0x7f852be0a130>{number = , name = (null)},
-- ::11.629 NSOperation[:] 这是任务2
-- ::11.629 NSOperation[:] 这是任务1,依赖于任务2
-- ::11.631 NSOperation[:] ,<NSThread: 0x7f852bd05190>{number = , name = main},

  从上面的执行结果中,我们可以得到几个结论:1.首先队列中的任务都是在子线程中执行的;2.队列中的任务是并发执行的。而常用到的添加依赖关系,以及操作完成之后回到主线程的方法在上面的代码中都有体现。

  需要说明的是,一旦将operation添加到队列中后,队列就拥有了这个操作,操作将不能从队列中删除,只能取消一个操作,或者取消所有的操作。取消一个操作的方法:

[operation cancel];

  取消所有操作的方法:

[queue cancelAllOperations];

  如果想要暂停操作的执行可以使用方法: [queue setSuspended:YES]; 来实现。但是暂停不会导致正在执行的操作被暂停,只会阻止队列调度新的操作执行。可以通过方法: [queue setSuspended:NO]; 来继续队列的执行。

  3、最后做一个简单的总结。NSInvocationOperation 和 NSBlockOperation的功能是开启一个线程任务,这个线程任务处于子线程和主线程取决于线程任务是在哪个线程中开辟的。这些任务可以使用线程任务队列NSOperationQueue来管理,当new一个队列时,队列所管理的任务都在子线程中执行.当使用[NSOperationQueue mainQueue]时,队列管理的任务在主线程中执行。

  以上就是这篇文章的多有内容,如果有不对或者不足的地方,请大家在评论中指出,大家一起讨论。

多线程之NSOperation和NSOperationQueue的更多相关文章

  1. iOS多线程之NSOperation,NSOperationQueue

    使用 NSOperation的方式有两种, 一种是用定义好的两个子类: NSInvocationOperation 和 NSBlockOperation. 另一种是继承NSOperation 如果你也 ...

  2. iOS多线程之NSOperation和NSOperationQueue的使用

    一:NSOperation 两个子类+重写main方法 NSInvocationOperation NSBlockOperation 有个类方法 BlockOprationWith: 还有就是自己个子 ...

  3. 多线程之NSOperation

    关于多线程会有一系列如下:多线程之概念解析 多线程之pthread, NSThread, NSOperation, GCD 多线程之NSThread 多线程之NSOperation 多线程之GCD

  4. iOS多线程之NSOperation详解

    使用NSOperation和NSOperationQueue进行多线程开发,只要将一个NSOperation(实际开发中需要使用其子类 NSInvocationOperation,NSBlockOpe ...

  5. iOS-多线程之NSOperation

    前言 这篇文章主要讲NSOperation的使用. What 使用NSOperation和NSOperationQueue进行多线程开发类似于线程池,只要将一个NSOperation(实际开发中需要使 ...

  6. IOS多线程之NSOperation学习总结

    NSOperation简介 1.NSOperation的作用 配合使用NSOperation和NSOperationQueue也能实现多线程编程 2.NSOperation和NSOperationQu ...

  7. iOS 多线程之NSOperation篇举例详解

    这篇博客是接着总篇iOS GCD NSOperation NSThread等多线程各种举例详解写的一个支篇.总篇也包含了此文的链接.本文讲解的知识点有NSBlockOperationClick,队列, ...

  8. [转] iOS多线程编程之NSOperation和NSOperationQueue的使用

    <iOS多线程编程之NSThread的使用> 介绍三种多线程编程和NSThread的使用,这篇介绍NSOperation的使用. 使用 NSOperation的方式有两种, 一种是用定义好 ...

  9. iOS多线程编程之NSOperation和NSOperationQueue的使用

    前一篇 <iOS多线程编程之NSThread的使用> 介绍三种多线程编程和NSThread的使用,这篇介绍NSOperation的使用. 使用 NSOperation的方式有两种, 一种是 ...

随机推荐

  1. Tips3:通过Layer下拉菜单来锁定游戏物体和控制物体的可视化

    通过把不同的游戏物体放在不同的Layer里面能对不同类的游戏物体进行很方便的控制,如果某些游戏物体创建后你不想再改动,如地面 装饰 什么的, 你可以通过点击Layer下拉菜单把它们锁定了 也可以通过控 ...

  2. Spring Remoting: Hessian--转

    原文地址:http://www.studytrails.com/frameworks/spring/spring-remoting-hessian.jsp Concept Overview The p ...

  3. php和java的memcached使用的兼容性问题解决过程

    1. 背景: php 使用memcached客户端设置一个key,java使用java-memcached-client去读,报错如下: ERROR|com.whalin.MemCached.MemC ...

  4. 自己动手模拟百分百<select>下拉列表

    浏览器默认的下拉确实不好用啊,主要是样式不好修改和统一. (一)下手之前先理清一下<select>的流程: 1.结构:<select> <option value=&qu ...

  5. OpenGL开发环境配置-Windows/MinGW/Clion/CMake

    因为某些原因,不想用过于臃肿的VS了,转而使用常用的jetbrains的CLion,Clion沿袭了jetbrans的优良传统,基本代码提示功能还是比较好的,不过就是对于windows不熟悉cmake ...

  6. IOS开发UI基础之UIScrollView

    什么是UIScrollView ● 移动设备的屏幕⼤大⼩小是极其有限的,因此直接展⽰示在⽤用户眼前的内容也相当有限 ● 当展⽰示的内容较多,超出⼀一个屏幕时,⽤用户可通过滚动⼿手势来查看屏幕以外的内容 ...

  7. SQL增删查改注意的事项

    一.新增 1.增加的时候,bit字段要用“0,1”表示false,和true: 2.时间字段,用单引号包括,里面要遵循基本时间格式: 3,不能为标识列(自动编号列)插入数据(特殊情况下:set ide ...

  8. 新增的querySelector、querySelectorAll测试

    从IE9开始DOM开始支持支持CSS的选择器了,DOM提供了两个接口 querySelector 得到一个DOM querySelectorAll 得到一组DOM 一个个的解释这些选择器也没有必要,我 ...

  9. javascript的 == 与 === 的区别

    1.对于基础类型,例如string,number ==和===是有区别的 1)不同类型间比较,==之比较“转化成同一类型后的值”看“值”是否相等,===如果类型不同,其结果就是不等 2)同类型比较,直 ...

  10. 跨平台的 SQL 客户端

    The major update to SQL client was to move to the .NET Core networking libraries instead of the nati ...