iOS自学之NSOperation、NSOperationQueue、Background
iOS中多线程编程主要分为NSThread、NSOperation和GCD,今天主要记录下自己在学习NSOperation中的点滴~如有不对的地方帮忙指出下,PS:人生第一次写blog,各位看官请轻虐,谢啦~
NSOperation是abstract类,不能直接使用,可以使用CocoTouch提供的NSBlockOperaion和NSInvocationOperation,也可以自己实现subclass。NSOperation可以理解为一个独立的任务,没有调度功能,真正利用NSOperation实现多线程的关键是NSOperationQueue,当NSOperation 添加到NSOperationQueue后,NSOperationQueue就会给队列中的NSOperation分配线程并调度。
1、NSOperationQueue为队列中的NSOperation分配不同的线程,测试代码如下:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSLog(@"main Thread is %p",[NSThread mainThread]);
[self testOperationWithQueue];
}
- (void)testOperationWithQueue
{
NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
NSBlockOperation *blockOperation1 = [NSBlockOperation blockOperationWithBlock:^{
[NSThread sleepForTimeInterval:];
NSLog(@"blockOperation1:current Thread is %p",[NSThread currentThread]);
}];
NSBlockOperation *blockOperation2 = [NSBlockOperation blockOperationWithBlock:^{
[NSThread sleepForTimeInterval:];
NSLog(@"blockOperation2:current Thread is %p",[NSThread currentThread]);
}];
NSBlockOperation *blockOperation3 = [NSBlockOperation blockOperationWithBlock:^{
[NSThread sleepForTimeInterval:];
NSLog(@"blockOperation3:current Thread is %p",[NSThread currentThread]);
}];
[operationQueue addOperation:blockOperation1];
[operationQueue addOperation:blockOperation2];
[operationQueue addOperation:blockOperation3];
}
打印结果:
-- ::22.747 TestNSOperation[:] main Thread is 0x7fc279f28130
-- ::31.288 TestNSOperation[:] blockOperation1:current Thread is 0x7fc279e0b8a0
-- ::31.288 TestNSOperation[:] blockOperation3:current Thread is 0x7fc279d661c0
-- ::31.288 TestNSOperation[:] blockOperation2:current Thread is 0x7fc279e064c0
从打印结果可以看出blockOperation1、blockOperation2、blockOperation3运行于不同的线程,是同时运行的,不需要等其他NSOperation,这也表明NSOperationQueue默认是并发执行。如果想要serial执行,则可以设置operationQueue.maxConcurrentOperationCount = 1;
2、不用NSOperationQueue,也可以直接调用NSOperation的start方法,但此时NSOepration运行在当前线程上,测试代码如下:
- (void)testOperationNotQueue
{
NSBlockOperation *blockOperation1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"blockOperation1:current Thread is %p",[NSThread currentThread]);
}];
NSBlockOperation *blockOperation2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"blockOperation2:current Thread is %p",[NSThread currentThread]);
}];
NSBlockOperation *blockOperation3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"blockOperation3:current Thread is %p",[NSThread currentThread]);
}];
[blockOperation1 start];
[blockOperation2 start];
[blockOperation3 start];
} //打印结果
-- ::20.497 TestNSOperation[:] main Thread is 0x7fb562427fd0
-- ::20.498 TestNSOperation[:] blockOperation1:current Thread is 0x7fb562427fd0
-- ::20.499 TestNSOperation[:] blockOperation2:current Thread is 0x7fb562427fd0
-- ::20.499 TestNSOperation[:] blockOperation3:current Thread is 0x7fb562427fd0
从打印结果可以看出blockOperation都运行在mainThread上。
3、NSOperation还提供了cancel功能,cancel不是强制把你的代码stop掉,只是改变了NSOperation内部的状态,该功能只能cancel掉Ready、Finish状态的NSOperation,不能cancel掉正在executing的NSOperation,测试代码如下:
- (void)testCancelOperation
{
NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
NSBlockOperation *blockOperation1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"start blockOperation1!");
[NSThread sleepForTimeInterval:];
if(blockOperation1.isCancelled)
{
NSLog(@"blockOperation2 cancelled!");
return;
}
NSLog(@"blockOperation1:current Thread is %p",[NSThread currentThread]);
}];
NSBlockOperation *blockOperation2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"blockOperation2:current Thread is %p",[NSThread currentThread]);
}];
NSBlockOperation *blockOperation3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"blockOperation3:current Thread is %p",[NSThread currentThread]);
}];
operationQueue.maxConcurrentOperationCount = ;
[operationQueue addOperation:blockOperation1];
[operationQueue addOperation:blockOperation2];
[operationQueue addOperation:blockOperation3];
[NSThread sleepForTimeInterval:];
NSLog(@"cancel blockOperation1");
[blockOperation1 cancel];
NSLog(@"cancel blockOperation2");
[blockOperation2 cancel];
NSLog(@"cancel blockOperation3");
[blockOperation3 cancel];
}
打印结果:
-- ::26.311 TestNSOperation[:] main Thread is 0x7ff02ae24e70
-- ::26.312 TestNSOperation[:] start blockOperation1!
-- ::28.318 TestNSOperation[:] cancel blockOperation1
-- ::28.318 TestNSOperation[:] cancel blockOperation2
-- ::28.318 TestNSOperation[:] cancel blockOperation3
-- ::36.315 TestNSOperation[:] blockOperation1:current Thread is 0x7ff02af1dec0
从打印结果可以看出不能cancel掉blockOperation1,而blockOperation2和blockOperation3则被成功地取消了。
4、NSOpertion还可以设置依赖,这一功能解决了需要按一定次序执行的situation,不多说直接上代码:
- (void)testOperationWithDependency
{
NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
NSBlockOperation *blockOperation1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"start blockOperation1");
}];
NSBlockOperation *blockOperation2 = [NSBlockOperation blockOperationWithBlock:^{
[NSThread sleepForTimeInterval:];
NSLog(@"start blockOperation2");
}];
NSBlockOperation *blockOperation3 = [NSBlockOperation blockOperationWithBlock:^{
[NSThread sleepForTimeInterval:];
NSLog(@"start blockOperation3");;
}];
[blockOperation1 addDependency:blockOperation2];
[blockOperation2 addDependency:blockOperation3];
[operationQueue addOperation:blockOperation1];
[operationQueue addOperation:blockOperation2];
[operationQueue addOperation:blockOperation3];
}
打印结果:
-- ::06.649 TestNSOperation[:] main Thread is 0x7fdaf9712a00
-- ::09.654 TestNSOperation[:] start blockOperation3
-- ::11.660 TestNSOperation[:] start blockOperation2
-- ::11.660 TestNSOperation[:] start blockOperation1
从打印的结果可以看出只有当依赖的Oepration执行完之后才开始执行自己。
5、当NSOperation添加到NSOperationQueue中,即使进入background(超过10min)NSOperation也会执行,真的不可思议啊,不是app进入到后台后如果不开定位服务、循环播放无声音乐、VOIP就最多运行10min吗?怎么超过10min的NSOperation还能执行啊,麻烦知道的网友告知一下,万分感谢~测试代码如下:
- (void)testBackgroundOperation
{
NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
NSBlockOperation *blockOperation1 = [NSBlockOperation blockOperationWithBlock:^{
[NSThread sleepForTimeInterval:*];
NSLog(@"blockOperation1:current Thread is %p",[NSThread currentThread]);
}];
[operationQueue addOperation:blockOperation1];
}
打印结果:
-- ::40.511 TestNSOperation[:] main Thread is 0x7faf41c0da30
-- ::43.095 TestNSOperation[:] applicationDidEnterBackground!
-- ::40.526 TestNSOperation[:] blockOperation1:current Thread is 0x7faf41e02f90
从打印结果可以看出,进入后台11min后,blockOperation1执行了,这是为什么呀!!!!
6、疑问
1、NSOperationQueue具体如何管理NSOperation的,网上也没找到相关文章,希望知道的朋友给个链接;2、测试中发现当NSOperationQueue是局部变量,只要NSOperation添加到NSOperationQueue中,即使程序运行到超出NSOperationQueue的生命周期外(NSOperationQueue变量自动释放了),NSOperation依然可以执行,比如如下代码,operationQueue应该是释放了,但blockOperation1、blockOperation2依然运行,其实这2个疑问都是关于NSOperationQueue如何管理NSOperation的,再次恳求知道的网友给个链接,谢谢哈~
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSLog(@"main Thread is %p",[NSThread mainThread]);
[self testOperationLeaveLifeCycle];
NSLog(@"leave operationQueue lifecycle");
}
- (void)testOperationLeaveLifeCycle
{
NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
NSBlockOperation *blockOperation1 = [NSBlockOperation blockOperationWithBlock:^{
[NSThread sleepForTimeInterval:];
NSLog(@"blockOperation1:current Thread is %p",[NSThread currentThread]);
}];
NSBlockOperation *blockOperation2 = [NSBlockOperation blockOperationWithBlock:^{
[NSThread sleepForTimeInterval:];
NSLog(@"blockOperation2:current Thread is %p",[NSThread currentThread]);
}];
[operationQueue addOperation:blockOperation1];
[operationQueue addOperation:blockOperation2];
}
打印结果:
-- ::49.649 TestNSOperation[:] main Thread is 0x7ff7e27241b0
-- ::49.650 TestNSOperation[:] leave operationQueue lifecycle
-- ::59.652 TestNSOperation[:] blockOperation1:current Thread is 0x7ff7e2517d20
-- ::09.653 TestNSOperation[:] blockOperation2:current Thread is 0x7ff7e2608a50
备注:上述所有的测试代码放到github上了,共勉~https://github.com/iOSGeek0829/testNSOperation
iOS自学之NSOperation、NSOperationQueue、Background的更多相关文章
- IOS多线程(NSOperation,NSOperationQueue)
含义:NSOperation,NSOperationQueue是什么. The NSOperation class is an abstract class you use to encapsulat ...
- iOS开发之NSOperation & NSOperationQueue
1.简介 (1) NSOperationQueue(操作队列)是由GCD提供的队列模型的Cocoa抽象,是一套Objective-C的API,为了使并发(多线程)编程变得更加简单,但效率比GCD略低. ...
- iOS中的多线程NSThread/GCD/NSOperation & NSOperationQueue
iOS多线程有四套多线程方案: Pthreads NSThread GCD NSOperation & NSOperationQueue 接下来我来一个一个介绍他们 Pthreads 在类Un ...
- iOS 多线程之 NSOperation 的基本使用
1.NSOperation,NSOperationQueue 简介 NSOperation,NSOperationQueue是苹果提供给我们的一套多线程解决方案.实际上 NSOperation.NSO ...
- iOS开发-多线程NSOperation和NSOperationQueue
上一篇文章稍微提及了一下NSThread的使用,NSThread能直观地控制线程对象,不过需要自己管理线程的生命周期,线程同步,用起来比较繁琐,而且比较容易出错.不过Apple给出了自己的解决方案NS ...
- IOS NSOperation&NSOperationQueue
NSOperation与NSOperationQueue的基本理论如下: 1.NSOperationQueue代表一个FIFO的队列,它负责管理系统提交的多个NSOperation,NSOp ...
- iOS 并发:NSOperation 与调度队列入门(1)
一直以来,并发都被视为 iOS 开发中的「洪水猛兽」.许多开发者都将其视为危险地带,唯恐避之而不及.更有谣传认为,多线程代码应该尽力避免.笔者同意,如果你对并发的了解不够深入,就容易造成危险.但是,危 ...
- iOS之多线程NSOperation
目前在 iOS 和 OS X 中有两套先进的同步 API 可供我们使用:NSOperation 和 GCD .其中 GCD 是基于 C 的底层的 API ,而 NSOperation 则是 GCD 实 ...
- iOS多线程编程--NSOperation(转)
这篇文章写得非常不错,基础用法都涉及到了,我把文章提到的例子都写到了demo里面, 原文地址: iOS多线程--彻底学会多线程之『NSOperation』 demo下载:https://github. ...
随机推荐
- C#学习笔记——面向对象、面向组件以及类型基础
C#学习笔记——面向对象.面向组件以及类型基础 目录 一 面向对象与面向组件 二 基元类型与 new 操作 三 值类型与引用类型 四 类型转换 五 相等性与同一性 六 对象哈希码 一 面向对象与面向组 ...
- iOS开发-布局基础
今天我学习了有关布局的知识,以下是我整理出来的需要注意的,也是我个人认为比较重要的细节. 一.自动约束 在我们设置好自动约束布局之后,有时会出现拖动滑动条,左边的Label会跟着放大缩小的问题. 这时 ...
- 学习Java设计模式的10条建议
设计模式在整个Java的学习路线图中扮演着承上启下的作用. 在整个软件生命周期中,唯一不变的就是变化.设计模式就是要在软件设计.编码中对现有问题的一种总结,并从中寻求应对变化的策略. 自己初次接触设计 ...
- 04---XML编程整理
一.XML概述 XML(eXtensible Markup Language),可扩展标记语言, 被设计的宗旨是传输数据,而非显示数据 W3C发布的,目前遵循1.0 ...
- Linux内核学习笔记2
http://www.cnblogs.com/bastard/category/412387.html
- MSSQL计算日期方法大全
通常,你需要获得当前日期和计算一些其他的日期,例如,你的程序可能需要判断一个月的第一天或者最后一天.你们大部分人大概都知道怎样把日期进行分割(年.月.日等),然后仅仅用分割出来的年.月.日等放在几个函 ...
- Apache Rewrite 服务器变量
Apache提供给rewirte模块的环境变量大概分成5个类型. 第一部分: HTTP headers 部分参数 参数名称: HTTP_USER_AGENT 样例参考值: Mozilla/5.0 (W ...
- Asp.Net 之 调用远程Web_Service
一.添加web service引用 1.右键 Web 项目 → “添加服务引用”: 2.右键已有的 App_WebReferences 文件夹 → “添加服务引用”: 二.引用远程web servic ...
- oracle的sql函数
只读事务set transaction read only当一个用户添加了只读事务,则查询时只会查到设置只读事务之前的内容,在并发量大的系统中,通过设置只读事务 便于统计 oracle的sql函数的使 ...
- <item name="android:windowNoTitle">true</item> 不起作用。标题栏未被隐藏
改变style.xml 加入 <item name="android:windowNoTitle">true</item> 按理说可以把标题栏隐藏,但是当s ...