美文网首页
NSOperation简单使用

NSOperation简单使用

作者: 水煮杰尼龟 | 来源:发表于2017-06-10 18:05 被阅读13次

NSOperation是OC中多线程技术的一种,是对GCD的OC包装.它包含队列(NSOperationQueue)和操作(NSOperation)两个基本要素.

NSInvocationOperation,NSBlockOperation

  • NSInvocationOperation
    先看看这两个。
//NSInvocationOperation 没用NSOperationQueue,在主线程调用执行
-(void)demo
{
    NSLog(@"---begin");
    NSInvocationOperation *operation=[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(test) object:nil];
    [operation start];
    NSLog(@"---end");
}
-(void)test
{
    [NSThread sleepForTimeInterval:4];
    for (int i=0; i<3; i++) {
        NSLog(@"---%d---%@",i,[NSThread currentThread]);
    }
}

编译结果如下:


NSInvocationOperation.png
  • NSBlockOperation
NSLog(@"---begin");
    NSBlockOperation *blockOp=[NSBlockOperation blockOperationWithBlock:^{
        [NSThread sleepForTimeInterval:4];
        for (int i=0; i<3; i++) {
            NSLog(@"---%d---%@",i,[NSThread currentThread]);
        }
    }];
    [blockOp start];
    NSLog(@"---end");

编译结果如下:

NSBlockOperation.png

从上面两个编译结果可以看出,没有使用NSOperationQueue时,要调用start开始执行,没有开启新的线程,所以---end需要等其执行完再打印。
NSBlockOperation还有一种使用方法addExecutionBlock:可以添加更多操作。

NSLog(@"---begin");
    //主线程中执行
    NSBlockOperation *blockOp=[NSBlockOperation blockOperationWithBlock:^{
        for (int i=0; i<3; i++) {
            NSLog(@"---%d---%@",i,[NSThread currentThread]);
        }
    }];
    //主线程和其他线程中执行
    [blockOp addExecutionBlock:^{
        [NSThread sleepForTimeInterval:2];
        for (int i=3; i<6; i++) {
            NSLog(@"---%d---%@",i,[NSThread currentThread]);
        }
    }];
    [blockOp addExecutionBlock:^{
        [NSThread sleepForTimeInterval:3];
        for (int i=6; i<9; i++) {
            NSLog(@"---%d---%@",i,[NSThread currentThread]);
        }
    }];
    [blockOp start];
    NSLog(@"---end");

编译结果如下:

addExecutionBlock.png

从我这里的结果来说blockOperationWithBlock里的任务是在主线程执行的,addExecutionBlock里的任务是在主线程和其他线程执行的。而且这里NSBlockOperation时阻塞了主线程的,NSBlockOperation的任务执行完之后才打印---end,NSOperation的start方法默认是同步执行任务.

NSOperationQueue

接下来就看看这个了。

  • [queue addOperation:invOp]
-(void)demo3
{
    NSLog(@"---begin");
    //队列
    NSOperationQueue *queue=[[NSOperationQueue alloc]init];
    queue.maxConcurrentOperationCount=-1;//最大并发数  1即为串行   默认-1并行
    //任务
    NSInvocationOperation *invOp=[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(test) object:nil];
    NSBlockOperation *blockOp=[NSBlockOperation blockOperationWithBlock:^{
        [NSThread sleepForTimeInterval:2];
        for (int i=3; i<6; i++) {
            NSLog(@"---%d---%@",i,[NSThread currentThread]);
        }
    }];
    [queue addOperation:invOp];
    [queue addOperation:blockOp];
    NSLog(@"---end");
}
-(void)test
{
    [NSThread sleepForTimeInterval:2];
    for (int i=0; i<3; i++) {
        NSLog(@"---%d---%@",i,[NSThread currentThread]);
    }
}

编译结果如下:

NSOperationQueue并发(maxConcurrentOperationCount=-1或大于1).png NSOperationQueue串行(maxConcurrentOperationCount=1).png
使用NSOperationQueue时,设置maxConcurrentOperationCount最大并发数,默认-1并行,1即为串行。
  • addOperationWithBlock
NSLog(@"---begin");
    //队列
    NSOperationQueue *queue=[[NSOperationQueue alloc]init];
    //任务
    [queue addOperationWithBlock:^{
        [self test];
    }];
    [queue addOperationWithBlock:^{
        [NSThread sleepForTimeInterval:2];
        for (int i=3; i<6; i++) {
            NSLog(@"---%d---%@",i,[NSThread currentThread]);
        }
    }];
    NSLog(@"---end");

效果一样,使用方法不一样而已。

  • 添加依赖和监听addDependency,completionBlock
NSLog(@"---begin");
    NSOperationQueue *queue=[[NSOperationQueue alloc]init];
    NSBlockOperation *blockOp=[NSBlockOperation blockOperationWithBlock:^{
        for (int i=0; i<3; i++) {
            NSLog(@"---%d---%@",i,[NSThread currentThread]);
        }
    }];
    NSBlockOperation *blockOp1=[NSBlockOperation blockOperationWithBlock:^{
        for (int i=3; i<6; i++) {
            NSLog(@"---%d---%@",i,[NSThread currentThread]);
        }
    }];
    NSBlockOperation *blockOp2=[NSBlockOperation blockOperationWithBlock:^{
        [NSThread sleepForTimeInterval:2];
        for (int i=6; i<9; i++) {
            NSLog(@"---%d---%@",i,[NSThread currentThread]);
        }
    }];
    //blockOp 依赖于blockOp1,即等blockOp1 执行完再执行 blockOp
    [blockOp addDependency:blockOp1];
    
    [queue addOperation:blockOp];
    [queue addOperation:blockOp1];
    [queue addOperation:blockOp2];
    blockOp.completionBlock=^{
        NSLog(@"---blockOp  over");
    };
    NSLog(@"---end");

编译结果如下:


依赖和监听.png

blockOp 依赖于blockOp1,等blockOp1里的任务执行完再执行blockOp的任务,blockOp执行完completionBlock回调打印---blockOp over. blockOp1和blockOp2执行顺序先后是不确定的(异步)。

  • NSOperationQueue的取消
-(void)demo6
{
    NSLog(@"---h begin");
    NSOperationQueue *queue=[[NSOperationQueue alloc]init];
    queue.maxConcurrentOperationCount=1;
    NSBlockOperation *blockOp=[NSBlockOperation blockOperationWithBlock:^{
        
        for (int i=0; i<3; i++) {
            NSLog(@"---h %d---%@",i,[NSThread currentThread]);
        }
    }];
    NSBlockOperation *blockOp1=[NSBlockOperation blockOperationWithBlock:^{
        [NSThread sleepForTimeInterval:1];
        for (int i=3; i<6; i++) {
            NSLog(@"---h %d---%@",i,[NSThread currentThread]);
        }
    }];
    NSBlockOperation *blockOp2=[NSBlockOperation blockOperationWithBlock:^{
        [NSThread sleepForTimeInterval:3];
        for (int i=6; i<9; i++) {
            NSLog(@"---h %d---%@",i,[NSThread currentThread]);
        }
    }];
    NSBlockOperation *blockOp3=[NSBlockOperation blockOperationWithBlock:^{
        [NSThread sleepForTimeInterval:4];
        for (int i=9; i<12; i++) {
            NSLog(@"---h %d---%@",i,[NSThread currentThread]);
        }
    }];
    
    [queue addOperation:blockOp];
    [queue addOperation:blockOp1];
    [queue addOperation:blockOp2];
    [queue addOperation:blockOp3];
    self.blockOperation=blockOp3;
    self.queue=queue;
    NSLog(@"---h end");
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    //[self.blockOperation cancel];
    [self.queue cancelAllOperations];
}

编译结果如下:

NSOperationQueue 取消所有cancelAllOperations.png NSOperation 取消单个cancel.png
  • NSOperationQueue的暂停恢复
-(void)demo6
{
    NSLog(@"---h begin");
    NSOperationQueue *queue=[[NSOperationQueue alloc]init];
    queue.maxConcurrentOperationCount=1;
    NSBlockOperation *blockOp=[NSBlockOperation blockOperationWithBlock:^{
        
        for (int i=0; i<3; i++) {
            NSLog(@"---h %d---%@",i,[NSThread currentThread]);
        }
    }];
    NSBlockOperation *blockOp1=[NSBlockOperation blockOperationWithBlock:^{
        [NSThread sleepForTimeInterval:1];
        for (int i=3; i<6; i++) {
            NSLog(@"---h %d---%@",i,[NSThread currentThread]);
        }
    }];
    NSBlockOperation *blockOp2=[NSBlockOperation blockOperationWithBlock:^{
        [NSThread sleepForTimeInterval:3];
        for (int i=6; i<9; i++) {
            NSLog(@"---h %d---%@",i,[NSThread currentThread]);
        }
    }];
    NSBlockOperation *blockOp3=[NSBlockOperation blockOperationWithBlock:^{
        [NSThread sleepForTimeInterval:4];
        for (int i=9; i<12; i++) {
            NSLog(@"---h %d---%@",i,[NSThread currentThread]);
        }
    }];
    
    [queue addOperation:blockOp];
    [queue addOperation:blockOp1];
    [queue addOperation:blockOp2];
    [queue addOperation:blockOp3];
    self.blockOperation=blockOp3;
    self.queue=queue;
    NSLog(@"---h end");
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    self.queue.suspended=!self.queue.suspended;
    if (self.queue.suspended) {
        NSLog(@"---h暂停");
    }else
    {
        NSLog(@"---h恢复");
    }
}

编译结果如下:

 ![NSOperationQueue的暂停恢复.png](https://img.haomeiwen.com/i3339381/4b450b2aad3becbf.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

NSOperationQueue有个suspended属性,当为YES的时候暂停,为NO时执行。当我点击屏幕时打印暂停,打印结果可以看出并没有马上暂停,它会把正在执行的任务完成才暂停。

---------------------个人对NSOperation的总结暂时就这么多吧。

相关文章

网友评论

      本文标题:NSOperation简单使用

      本文链接:https://www.haomeiwen.com/subject/zpaqqxtx.html