zoukankan      html  css  js  c++  java
  • 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)testOperationNotQueue
     2 {
     3     NSBlockOperation *blockOperation1 = [NSBlockOperation blockOperationWithBlock:^{
     4         NSLog(@"blockOperation1:current Thread is %p",[NSThread currentThread]);
     5     }];
     6     NSBlockOperation *blockOperation2 = [NSBlockOperation blockOperationWithBlock:^{
     7         NSLog(@"blockOperation2:current Thread is %p",[NSThread currentThread]);
     8     }];
     9     NSBlockOperation *blockOperation3 = [NSBlockOperation blockOperationWithBlock:^{
    10         NSLog(@"blockOperation3:current Thread is %p",[NSThread currentThread]);
    11     }];
    12     [blockOperation1 start];
    13     [blockOperation2 start];
    14     [blockOperation3 start];
    15 }
    16 
    17 //打印结果
    18 2015-05-30 00:22:20.497 TestNSOperation[12968:1196358] main Thread is 0x7fb562427fd0
    19 2015-05-30 00:22:20.498 TestNSOperation[12968:1196358] blockOperation1:current Thread is 0x7fb562427fd0
    20 2015-05-30 00:22:20.499 TestNSOperation[12968:1196358] blockOperation2:current Thread is 0x7fb562427fd0
    21 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

     

  • 相关阅读:
    BZOJ.3453.tyvj 1858 XLkxc(拉格朗日插值)
    BZOJ.5339.[TJOI2018]教科书般的亵渎(拉格朗日插值) & 拉格朗日插值学习笔记
    BZOJ.5461.[PKUWC2018]Minimax(DP 线段树合并)
    AGC 014E.Blue and Red Tree(思路 启发式合并)
    BZOJ.4199.[NOI2015]品酒大会(后缀自动机 树形DP)
    BZOJ.4199.[NOI2015]品酒大会(后缀数组 单调栈)
    BZOJ.4052.[Cerc2013]Magical GCD(思路)
    BZOJ.3307.雨天的尾巴(dsu on tree/线段树合并)
    字节跳动冬令营网络赛 D.The Easiest One(贪心 数位DP)
    BZOJ.1210.[HNOI2004]邮递员(插头DP Hash 高精)
  • 原文地址:https://www.cnblogs.com/NerdFooProgrammer/p/4539741.html
Copyright © 2011-2022 走看看