NSOpertation是一套OC的API,是对GCD进行的Cocoa抽象。

NSOperation有两种不同类型的队列,主队列和自定义队列。

主队列运行于主线程上,自定义队列在后台运行。

【NSBlockOperation】

通过Block创建任务,下面比较主队列和自定义队列的区别:

将自定义队列声明为成员变量,并进行初始化:

@property (nonatomic, strong) NSOperationQueue *myqueue;
self.myqueue = [[NSOperationQueue alloc] init];

获取主队列的方法为[NSOperationQueue mainQueue]。

队列有一个方法addOperationWithBlock方法用于添加一个用Block描述的任务。

具体代码为:

- (void)NSBlockOperation{

    // 自定义队列在子线程中运行。
[self.myqueue addOperationWithBlock:^{
NSLog(@"%@",[NSThread currentThread]);
}];
// 主队列任务在主线程中运行。
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
NSLog(@"%@",[NSThread currentThread]);
}]; }

执行这个方法,得到的结果如下,可见与上面的描述相符。

2015-02-17 10:46:15.308 NSOpertaion[709:17138] <NSThread: 0x7b9aa440>{number = 2, name = (null)}
2015-02-17 10:46:15.319 NSOpertaion[709:17067] <NSThread: 0x7b978550>{number = 1, name = main}

【NSInvocationOperation】

需要定义一个回调方法,好处是可以接收一个id类型的object作为消息。

例如:

- (void)NSInvocationOperation{

    NSDictionary *msg = @{@"name" : @"op",@"message" : @"hello"};
NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(InvocationCall:) object:msg];
[self.myqueue addOperation:op]; }

实现回调方法:

- (void)InvocationCall:(id)obj{
NSLog(@"%@ with object %@",[NSThread currentThread],obj);
}

调用后,打印的结果如下,可以看到object对象被传了过来。

2015-02-17 10:56:03.764 NSOpertaion[812:26537] <NSThread: 0x7ba6eb10>{number = 2, name = (null)} with object {
message = hello;
name = op;
}

【任务执行顺序】

在默认情况下,自定义队列是并行队列,执行无序;而主队列为串行队列,有序执行。下面进行实验验证说法:

    // 自定义队列在子线程中运行。
for (int i = 0; i < 9; i++) {
[self.myqueue addOperationWithBlock:^{
NSLog(@"%@ with no %d",[NSThread currentThread],i);
}];
} // 主队列任务在主线程中运行。
for (int i = 0; i < 9; i++) {
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
NSLog(@"%@ with no %d",[NSThread currentThread],i);
}];
}

执行结果如下,可见与上面的描述相同。

2015-02-17 11:04:08.421 NSOpertaion[919:32337] <NSThread: 0x7bf91f50>{number = 9, name = (null)} with no 6
2015-02-17 11:04:08.421 NSOpertaion[919:32331] <NSThread: 0x7bf91c10>{number = 4, name = (null)} with no 1
2015-02-17 11:04:08.421 NSOpertaion[919:32338] <NSThread: 0x7bf915c0>{number = 6, name = (null)} with no 5
2015-02-17 11:04:08.421 NSOpertaion[919:32336] <NSThread: 0x7dab62c0>{number = 7, name = (null)} with no 4
2015-02-17 11:04:08.421 NSOpertaion[919:32339] <NSThread: 0x7dab61b0>{number = 3, name = (null)} with no 7
2015-02-17 11:04:08.421 NSOpertaion[919:32330] <NSThread: 0x7dab6110>{number = 2, name = (null)} with no 0
2015-02-17 11:04:08.421 NSOpertaion[919:32341] <NSThread: 0x7d97b3f0>{number = 5, name = (null)} with no 8
2015-02-17 11:04:08.421 NSOpertaion[919:32328] <NSThread: 0x7be6d450>{number = 10, name = (null)} with no 3
2015-02-17 11:04:08.421 NSOpertaion[919:32329] <NSThread: 0x7dab6450>{number = 8, name = (null)} with no 2
2015-02-17 11:04:08.448 NSOpertaion[919:32281] <NSThread: 0x7d96f040>{number = 1, name = main} with no 0
2015-02-17 11:04:08.449 NSOpertaion[919:32281] <NSThread: 0x7d96f040>{number = 1, name = main} with no 1
2015-02-17 11:04:08.449 NSOpertaion[919:32281] <NSThread: 0x7d96f040>{number = 1, name = main} with no 2
2015-02-17 11:04:08.449 NSOpertaion[919:32281] <NSThread: 0x7d96f040>{number = 1, name = main} with no 3
2015-02-17 11:04:08.450 NSOpertaion[919:32281] <NSThread: 0x7d96f040>{number = 1, name = main} with no 4
2015-02-17 11:04:08.450 NSOpertaion[919:32281] <NSThread: 0x7d96f040>{number = 1, name = main} with no 5
2015-02-17 11:04:08.450 NSOpertaion[919:32281] <NSThread: 0x7d96f040>{number = 1, name = main} with no 6
2015-02-17 11:04:08.450 NSOpertaion[919:32281] <NSThread: 0x7d96f040>{number = 1, name = main} with no 7
2015-02-17 11:04:08.450 NSOpertaion[919:32281] <NSThread: 0x7d96f040>{number = 1, name = main} with no 8

【自定义队列顺序执行】

使用NSBlockOperation对象的addDependency设置依赖关系,只有依赖的对象执行完毕后,自己才能执行。

例如下面的例子,三个任务要顺序执行,先下载,再处理,最后显示,通过这样的设定可以保证顺序:

- (void)SerialOperation{

    NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"下载");
}];
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"处理");
}];
NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"显示");
}]; [op2 addDependency:op1];
[op3 addDependency:op2]; [self.myqueue addOperation:op1];
[self.myqueue addOperation:op2];
[self.myqueue addOperation:op3]; }

注意这个执行和串行队列的异步任务不同点是,串行队列的异步任务仅仅开一个线程;自定义队列的顺序执行可能开辟多个但不会太多个线程。

注意上面的代码有一定的问题,因为显示只有主线程可以处理,所以op3应该放入主线程。

Tip:依赖关系可以跨队列,因此op3依赖op2在主线程中仍然有效,只需要修改op3的入队代码为:

[[NSOperationQueue mainQueue] addOperation:op3];

Tip:注意避开循环依赖,程序会崩溃。

【设定多线程的最大开销】

设定同时执行的最大线程数:通过队列的setMaxConcurrentOperationCount方法来设定,例如:

[self.myqueue setMaxConcurrentOperationCount:3];

应用场景:网络通信,例如3G开3个子线程,WIFI开6个子线程。

Tip:线程的开销主要是CPU和内存,还会耗电,因此应该考虑软件的能耗。

Tip:AFNetworing的底层是使用GCD开发的,接口是NSOperation。

(五十六)iOS多线程之NSOperation的更多相关文章

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

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

  2. iOS多线程之NSOperation详解

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

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

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

  4. iOS多线程之NSOperation,NSOperationQueue

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

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

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

  6. ios多线程之NSOperation

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

  7. iOS多线程之8.NSOPeration的其他用法

      本文主要对NSOPeration的一些重点属性和方法做出介绍,以便大家可以更好的使用NSOPeration. 1.添加依赖 - (void)addDependency:(NSOperation * ...

  8. iOS多线程之GCD小记

    iOS多线程之GCD小记 iOS多线程方案简介 从各种资料中了解到,iOS中目前有4套多线程的方案,分别是下列4中: 1.Pthreads 这是一套可以在很多操作系统上通用的多线程API,是基于C语言 ...

  9. 【Visual C++】游戏开发五十六 浅墨DirectX教程二十三 打造游戏GUI界面(一)

    本系列文章由zhmxy555(毛星云)编写,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/16384009 作者:毛星云 ...

随机推荐

  1. python学习之路网络编程篇(第五篇)-续篇

    Python堡垒机实现之基础知识 一般的堡垒机必须要具备以下5个基本功能: 1.权限控制 2.执行命令 3.上传下载文件 4.远程登录 5.记录操作 权限控制 说明:根据不同的登录用户分配不同的可管理 ...

  2. 【python标准库模块三】Os模块和Sys模块学习

    Os模块 导入os模块 import os 获取当前工作目录 os.getcwd() 切换目录,跟linux中的cd一样 os.chdir("文件夹名") 递归生成文件夹 os.m ...

  3. PHP 文件

    PHP 文件处理 fopen() 函数用于在 PHP 中打开文件. 打开文件 fopen() 函数用于在 PHP 中打开文件. 此函数的第一个参数含有要打开的文件的名称,第二个参数规定了使用哪种模式来 ...

  4. PHP 5 MySQLi 函数

    在 PHP 中使用 MySQLi 函数需要注意的是:你需要添加对 MySQLi 扩展的支持. PHP MySQLi 简介 PHP MySQLi = PHP MySQL Improved! MySQLi ...

  5. Android动态修改ToolBar的Menu菜单

    Android动态修改ToolBar的Menu菜单 效果图 实现 实现很简单,就是一个具有3个Action的Menu,在我们滑动到不同状态的时候,把对应的Action隐藏了. 开始上货 Menu Me ...

  6. RunLoop总结:RunLoop的应用场景(五)

    今天要介绍的RunLoop应用场景感觉很酷炫,我们可能不常用到,但是对于做Crash 收集的 SDK可能会用得比较频繁吧.相比关于RunLoop 可以让应用起死回生,大家都听说过,可是怎么实现呢?今天 ...

  7. 23 服务的启动Demo2

    MainActivity.java package com.qf.day23_service_demo2; import android.app.Activity; import android.co ...

  8. Dynamics CRM 权限整理二

    接上篇http://blog.csdn.net/vic0228/article/details/50510605,继续列举CRM相关权限 prvReadBusinessUnit privilege(I ...

  9. SQLite Insert 语句(http://www.w3cschool.cc/sqlite/sqlite-insert.html)

    SQLite Insert 语句 SQLite 的 INSERT INTO 语句用于向数据库的某个表中添加新的数据行. 语法 INSERT INTO 语句有两种基本语法,如下所示: INSERT IN ...

  10. Android时遇到R.java was modified manually! Reverting to generated version!

    欢迎关注公众号,每天推送Android技术文章,二维码如下:(可扫描) 进入 eclipse后clipse Menu >Projects > clean 这么做就把R文件删了,但是别担心, ...