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分配不同的线程,测试代码如下:

 1 - (void)viewDidLoad {
 2     [super viewDidLoad];
 3     // Do any additional setup after loading the view, typically from a nib.
 4     NSLog(@"main Thread is %p",[NSThread mainThread]);
 5     [self testOperationWithQueue];
 6 }
 7 - (void)testOperationWithQueue
 8 {
 9     NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
10     NSBlockOperation *blockOperation1 = [NSBlockOperation blockOperationWithBlock:^{
11         [NSThread sleepForTimeInterval:1];
12         NSLog(@"blockOperation1:current Thread is %p",[NSThread currentThread]);
13     }];
14     NSBlockOperation *blockOperation2 = [NSBlockOperation blockOperationWithBlock:^{
15         [NSThread sleepForTimeInterval:1];
16         NSLog(@"blockOperation2:current Thread is %p",[NSThread currentThread]);
17     }];
18     NSBlockOperation *blockOperation3 = [NSBlockOperation blockOperationWithBlock:^{
19         [NSThread sleepForTimeInterval:1];
20         NSLog(@"blockOperation3:current Thread is %p",[NSThread currentThread]);
21     }];
22     [operationQueue addOperation:blockOperation1];
23     [operationQueue addOperation:blockOperation2];
24     [operationQueue addOperation:blockOperation3];
25 }
26
27 打印结果:
28 2015-05-29 23:34:22.747 TestNSOperation[12730:1171127] main Thread is 0x7fc279f28130
29 2015-05-29 23:34:31.288 TestNSOperation[12730:1171237] blockOperation1:current Thread is 0x7fc279e0b8a0
30 2015-05-29 23:34:31.288 TestNSOperation[12730:1171238] blockOperation3:current Thread is 0x7fc279d661c0
31 2015-05-29 23:34:31.288 TestNSOperation[12730:1171235] blockOperation2:current Thread is 0x7fc279e064c0

从打印结果可以看出blockOperation1、blockOperation2、blockOperation3运行于不同的线程,是同时运行的,不需要等其他NSOperation,这也表明NSOperationQueue默认是并发执行。如果想要serial执行,则可以设置operationQueue.maxConcurrentOperationCount = 1;

  2、不用NSOperationQueue,也可以直接调用NSOperation的start方法,但此时NSOepration运行在当前线程上,测试代码如下:

 1 - (void)testOperationWithQueue
 2 {
 3     NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
 4     NSBlockOperation *blockOperation1 = [NSBlockOperation blockOperationWithBlock:^{
 5         [NSThread sleepForTimeInterval:1];
 6         NSLog(@"blockOperation1:current Thread is %p",[NSThread currentThread]);
 7     }];
 8     NSBlockOperation *blockOperation2 = [NSBlockOperation blockOperationWithBlock:^{
 9         [NSThread sleepForTimeInterval:1];
10         NSLog(@"blockOperation2:current Thread is %p",[NSThread currentThread]);
11     }];
12     NSBlockOperation *blockOperation3 = [NSBlockOperation blockOperationWithBlock:^{
13         [NSThread sleepForTimeInterval:1];
14         NSLog(@"blockOperation3:current Thread is %p",[NSThread currentThread]);
15     }];
16     [operationQueue addOperation:blockOperation1];
17     [operationQueue addOperation:blockOperation2];
18     [operationQueue addOperation:blockOperation3];
19 }
20 打印结果:
21 2015-05-30 00:22:20.497 TestNSOperation[12968:1196358] main Thread is 0x7fb562427fd0
22 2015-05-30 00:22:20.498 TestNSOperation[12968:1196358] blockOperation1:current Thread is 0x7fb562427fd0
23 2015-05-30 00:22:20.499 TestNSOperation[12968:1196358] blockOperation2:current Thread is 0x7fb562427fd0
24 2015-05-30 00:22:20.499 TestNSOperation[12968:1196358] blockOperation3:current Thread is 0x7fb562427fd0

从打印结果可以看出blockOperation都运行在mainThread上。

  3、NSOperation还提供了cancel功能,cancel不是强制把你的代码stop掉,只是改变了NSOperation内部的状态,该功能只能cancel掉Ready、Finish状态的NSOperation,不能cancel掉正在executing的NSOperation,测试代码如下:

 1 - (void)testCancelOperation
 2 {
 3     NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
 4     NSBlockOperation *blockOperation1 = [NSBlockOperation blockOperationWithBlock:^{
 5         NSLog(@"start blockOperation1!");
 6         [NSThread sleepForTimeInterval:10];
 7         if(blockOperation1.isCancelled)
 8         {
 9             NSLog(@"blockOperation2 cancelled!");
10             return;
11         }
12         NSLog(@"blockOperation1:current Thread is %p",[NSThread currentThread]);
13     }];
14     NSBlockOperation *blockOperation2 = [NSBlockOperation blockOperationWithBlock:^{
15         NSLog(@"blockOperation2:current Thread is %p",[NSThread currentThread]);
16     }];
17     NSBlockOperation *blockOperation3 = [NSBlockOperation blockOperationWithBlock:^{
18         NSLog(@"blockOperation3:current Thread is %p",[NSThread currentThread]);
19     }];
20     operationQueue.maxConcurrentOperationCount = 1;
21     [operationQueue addOperation:blockOperation1];
22     [operationQueue addOperation:blockOperation2];
23     [operationQueue addOperation:blockOperation3];
24     [NSThread sleepForTimeInterval:2];
25     NSLog(@"cancel blockOperation1");
26     [blockOperation1 cancel];
27     NSLog(@"cancel blockOperation2");
28     [blockOperation2 cancel];
29     NSLog(@"cancel blockOperation3");
30     [blockOperation3 cancel];
31 }
32 打印结果:
33 2015-05-30 00:27:26.311 TestNSOperation[13009:1199727] main Thread is 0x7ff02ae24e70
34 2015-05-30 00:27:26.312 TestNSOperation[13009:1199831] start blockOperation1!
35 2015-05-30 00:27:28.318 TestNSOperation[13009:1199727] cancel blockOperation1
36 2015-05-30 00:27:28.318 TestNSOperation[13009:1199727] cancel blockOperation2
37 2015-05-30 00:27:28.318 TestNSOperation[13009:1199727] cancel blockOperation3
38 2015-05-30 00:27:36.315 TestNSOperation[13009:1199831] blockOperation1:current Thread is 0x7ff02af1dec0

从打印结果可以看出不能cancel掉blockOperation1,而blockOperation2和blockOperation3则被成功地取消了。

  4、NSOpertion还可以设置依赖,这一功能解决了需要按一定次序执行的situation,不多说直接上代码:

 1 - (void)testOperationWithDependency
 2 {
 3     NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
 4     NSBlockOperation *blockOperation1 = [NSBlockOperation blockOperationWithBlock:^{
 5         NSLog(@"start blockOperation1");
 6     }];
 7     NSBlockOperation *blockOperation2 = [NSBlockOperation blockOperationWithBlock:^{
 8         [NSThread sleepForTimeInterval:2];
 9         NSLog(@"start blockOperation2");
10     }];
11     NSBlockOperation *blockOperation3 = [NSBlockOperation blockOperationWithBlock:^{
12         [NSThread sleepForTimeInterval:3];
13         NSLog(@"start blockOperation3");;
14     }];
15     [blockOperation1 addDependency:blockOperation2];
16     [blockOperation2 addDependency:blockOperation3];
17     [operationQueue addOperation:blockOperation1];
18     [operationQueue addOperation:blockOperation2];
19     [operationQueue addOperation:blockOperation3];
20 }
21 打印结果:
22 2015-05-31 18:18:06.649 TestNSOperation[15541:1510356] main Thread is 0x7fdaf9712a00
23 2015-05-31 18:18:09.654 TestNSOperation[15541:1510384] start blockOperation3
24 2015-05-31 18:18:11.660 TestNSOperation[15541:1510384] start blockOperation2
25 2015-05-31 18:18:11.660 TestNSOperation[15541:1510384] start blockOperation1

从打印的结果可以看出只有当依赖的Oepration执行完之后才开始执行自己。

  5、当NSOperation添加到NSOperationQueue中,即使进入background(超过10min)NSOperation也会执行,真的不可思议啊,不是app进入到后台后如果不开定位服务、循环播放无声音乐、VOIP就最多运行10min吗?怎么超过10min的NSOperation还能执行啊,麻烦知道的网友告知一下,万分感谢~测试代码如下:

 1 - (void)testBackgroundOperation
 2 {
 3     NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
 4     NSBlockOperation *blockOperation1 = [NSBlockOperation blockOperationWithBlock:^{
 5         [NSThread sleepForTimeInterval:11*60];
 6         NSLog(@"blockOperation1:current Thread is %p",[NSThread currentThread]);
 7     }];
 8     [operationQueue addOperation:blockOperation1];
 9 }
10 打印结果:
11 2015-05-30 01:04:40.511 TestNSOperation[13252:1219020] main Thread is 0x7faf41c0da30
12 2015-05-30 01:04:43.095 TestNSOperation[13252:1219020] applicationDidEnterBackground!
13 2015-05-30 01:15:40.526 TestNSOperation[13252:1219146] blockOperation1:current Thread is 0x7faf41e02f90

从打印结果可以看出,进入后台11min后,blockOperation1执行了,这是为什么呀!!!!

  6、疑问

  1、NSOperationQueue具体如何管理NSOperation的,网上也没找到相关文章,希望知道的朋友给个链接;2、测试中发现当NSOperationQueue是局部变量,只要NSOperation添加到NSOperationQueue中,即使程序运行到超出NSOperationQueue的生命周期外(NSOperationQueue变量自动释放了),NSOperation依然可以执行,比如如下代码,operationQueue应该是释放了,但blockOperation1、blockOperation2依然运行,其实这2个疑问都是关于NSOperationQueue如何管理NSOperation的,再次恳求知道的网友给个链接,谢谢哈~

 1 - (void)viewDidLoad {
 2     [super viewDidLoad];
 3     // Do any additional setup after loading the view, typically from a nib.
 4     NSLog(@"main Thread is %p",[NSThread mainThread]);
 5     [self testOperationLeaveLifeCycle];
 6     NSLog(@"leave operationQueue lifecycle");
 7 }
 8 - (void)testOperationLeaveLifeCycle
 9 {
10     NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
11     NSBlockOperation *blockOperation1 = [NSBlockOperation blockOperationWithBlock:^{
12         [NSThread sleepForTimeInterval:10];
13         NSLog(@"blockOperation1:current Thread is %p",[NSThread currentThread]);
14     }];
15     NSBlockOperation *blockOperation2 = [NSBlockOperation blockOperationWithBlock:^{
16         [NSThread sleepForTimeInterval:20];
17         NSLog(@"blockOperation2:current Thread is %p",[NSThread currentThread]);
18     }];
19     [operationQueue addOperation:blockOperation1];
20     [operationQueue addOperation:blockOperation2];
21 }
22 打印结果:
23 2015-05-30 01:25:49.649 TestNSOperation[13358:1228380] main Thread is 0x7ff7e27241b0
24 2015-05-30 01:25:49.650 TestNSOperation[13358:1228380] leave operationQueue lifecycle
25 2015-05-30 01:25:59.652 TestNSOperation[13358:1228482] blockOperation1:current Thread is 0x7ff7e2517d20
26 2015-05-30 01:26:09.653 TestNSOperation[13358:1228481] blockOperation2:current Thread is 0x7ff7e2608a50

备注:上述所有的测试代码放到github上了,共勉~https://github.com/iOSGeek0829/testNSOperation

时间: 2024-10-12 14:56:57

iOS自学之NSOperation、NSOperationQueue、Background的相关文章

iOS 多线程 NSThread NSOperation NSOperationQueue GCD 线程锁 线程阻塞

iPhone中的线程应用并不是无节制的,官方给出的资料显示,iPhone OS下的主线程的堆栈大小是1M,第二个线程开始就是512KB,并且该值不能通过编译器开关或线程API函数来更改,只有主线程有直接修改UI的能力,所以一些数据层面可以开辟线程来操作进行,iOS线程的操作方法有NSThread NSOperation NSOperationQueue GCD: NSThread方法有 //NSThread自动 - (IBAction)didClickNSThreadAutoButtonActi

iOS开发之NSOperation & NSOperationQueue

1.简介 (1) NSOperationQueue(操作队列)是由GCD提供的队列模型的Cocoa抽象,是一套Objective-C的API,为了使并发(多线程)编程变得更加简单,但效率比GCD略低.在实际开发中NSOperationQueue是首选. (2) GCD提供了更加底层的控制,而操作队列则在GCD之上实现了一些方便的功能,这些功能对于开发者而言通常是最好最安全的选择. 队列及操作 (1)NSOperationQueue有两种不同类型的队列:主队列和自定义队列 (2)主队列运行在主线程

【iOS】多线程NSOperation

NSOperation是苹果封装的一套多线程的东西,不像GCD是纯C语言的,这个是OC的.但相比较之下GCD会更快一些,但本质上NSOPeration是多GDC的封装. 一.NSOperation与GCD的比较 GCD是基于c的底层api,NSOperation属于object-c类.ios首先引入的是NSOperation,IOS4之后引入了GCD和NSOperationQueue并且其内部是用gcd实现的. GCD优点:GCD主要与block结合使用.代码简洁高效.执行效率稍微高点. NSO

iOS多线程技术—NSOperation用法

iOS多线程技术—NSOperation用法 一.NSOperation简介 1.简单说明 NSOperation的作?:配合使用NSOperation和NSOperationQueue也能实现多线程编程 NSOperation和NSOperationQueue实现多线程的具体步骤: (1)先将需要执行的操作封装到一个NSOperation对象中 (2)然后将NSOperation对象添加到NSOperationQueue中 (3)系统会?动将NSOperationQueue中的NSOperat

NSOperation && NSOperationQueue使用

NSOperation&&NSOperationQueue使用 NSOperation 用来封装我们想要异步执行的任务(下载图片/图片滤镜操作), NSOperation 是一个抽象类,与 NSNumber 是一样,本身并没有多少的用途,不能向 NSOperationQueue 中添加操作.有用的是它的子类 NSInvocationOperation 继承自 NSOperation 的子类,能将一个方法成封装任务,并提交给NSOperationQueue 调度 同步执行 1 NSInvoc

给iOS开发自学的建议,附iOS自学资源

文/上嵌科技(简书作者) 原文链接:http://www.jianshu.com/p/4b7e7aceddf5 著作权归作者所有,转载请联系作者获得授权,并标注"简书作者". 很多同学都在大学期间,或在职期间想自学ios开发或者Android开发,今天小编就给大家集中介绍iOS开发自学方法和建议,附送iOS自学资料. ios开发自学者的建议从新手到入行 不要听信从0基础到精通.到专家,学习编程最最关键的是从新手到入门,当你入门了,你自我学习.自我驱动的能力会更强,没有入门,当你过了学习

我的iOS自学之路

学习一门语言需要坚持的毅力,本篇分享一下我的iOS自学之路,以及学习中总结的经验! 1. 为什么要学习iOS? 2014年11月左右进入某家公司,使用Java语言进行移动App接口开发工作,工作中认识了以为iOS开发同事,后来逐渐了解到iOS的市场行情和薪资待遇,大概是在培训机构培训4个月第一份工作大概能拿到1万左右,瞬间感觉做Java开发的受到一万点伤害!大学刚毕业都能拿到1W,我做Java 已经工作X年了还不如刚毕业的,那时开始慢慢关注iOS,了解到那时移动开发很火,以后发展应该很好!从那时

IOS多线程--NSOperation\NSOperationQueue

iOS中,有多种多线程方式,但是,苹果公司建议我们用NSOperation技术 1.GCD是纯C的,对面向对象的程序员不友好 2.GCD对编程管理还不是很强大 NSOperation 其实底层实现是基于GCD来做的 dispatch_queue_t ==  NSOperationQueue dispatch_async == NSOperation dispatch_sync  == NSOperation NSOperation是个抽象类 使用它的两个子类 NSInvocationOperat

iOS开发-多线程NSOperation和NSOperationQueue

上一篇文章稍微提及了一下NSThread的使用,NSThread能直观地控制线程对象,不过需要自己管理线程的生命周期,线程同步,用起来比较繁琐,而且比较容易出错.不过Apple给出了自己的解决方案NSOperation,它本身是抽象基类,因此必须使用它的子类,使用NSOperation子类的方式有NSInvocationOperation和NSBlockOperation两种方式,先补充一下NSThread的用法: NSThread获取当前线程: [NSThread currentThread]