文档章节

NSOperation & NSOperationQueue

小春0618
 小春0618
发布于 2015/01/27 09:21
字数 1130
阅读 24
收藏 0

NSOperation & NSOperationQueue

从头文件NSOperation.h来看接口是非常的简洁,NSOperation本身是一个抽象类,定义了一个要执行的工 作,NSOperationQueue是一个工作队列,当工作加入到队列后,NSOperationQueue会自动按照优先顺序及工作的从属依赖关系 (如果有的话)组织执行。

NSOperation是没法直接使用的,它只是提供了一个工作的基本逻辑,具体实现还是需要你通过定义自己的NSOperation子类来获得。如果有必要也可以不将NSOperation加入到一个NSOperationQueue中去执行,直接调用起-start也可以直接执行。

在继承NSOpertaion后,对于非并发的工作,只需要实现NSOperation子类的main方法:

NSBlockOperation* theOp = [NSBlockOperation blockOperationWithBlock: ^{      NSLog(@"Beginning operation.\n");      // Do some work.   }];

由于NSOperation的工作是可以取消Cancel的,那么你在main方法处理工作时就需要不断轮询[self isCancelled]确认当前的工作是否被取消了。

如果要支持并发工作,那么NSOperation子类需要至少override这四个方法:

  • start

  • isConcurrent

  • isExecuting

  • isFinished

实现了一个基于Operation的下载器,在Sample Code中可以下载。

- (void)operationDidStart
{    
    [self.lock lock];    
    NSMutableURLRequest* request = [[NSMutableURLRequest alloc] initWithURL:self.URL                                                                cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:self.timeoutInterval];    
    [request setHTTPMethod: @"GET"];        
    self.connection =[[NSURLConnection alloc] initWithRequest:request                                                     delegate:self startImmediately:NO];   
    [self.connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];    
    [self.connection start];    
    [self.lock unlock];
}

- (void)operationDidFinish
{    
    [self.lock lock];    
    [self willChangeValueForKey:@"isFinished"];    
    [self willChangeValueForKey:@"isExecuting"];        
    self.executing = NO;    
    self.finished = YES;        
    [self didChangeValueForKey:@"isExecuting"];    
    [self didChangeValueForKey:@"isFinished"];    
    [self.lock unlock];
}

- (void)start
{    
    [self.lock lock];   
     
    if ([self isCancelled])    {        
        [self willChangeValueForKey:@"isFinished"];        
        self.finished = YES;        
        [self didChangeValueForKey:@"isFinished"];        
        return;    
    }        
    
    [self willChangeValueForKey:@"isExecuting"];    
    [self performSelector:@selector(operationDidStart) onThread:[[self class] networkThread] withObject:nil waitUntilDone:NO];    
    self.executing = YES;    
    [self didChangeValueForKey:@"isExecuting"];    
    
    [self.lock unlock];
}

- (void)cancel
{    
    [self.lock lock];    
    [super cancel];    
    if (self.connection)    {        
        [self.connection cancel];        
        self.connection = nil;    
    }        
    
    [self.lock unlock];
}

- (BOOL)isConcurrent 
{    
    return YES;
}

- (BOOL)isExecuting 
{    
    return self.executing;
}

- (BOOL)isFinished 
{    
    return self.finished;
}


start方法是工作的入口,通常是你用来设置线程或者其他执行工作任务需要的运行环境的,注意不要调用[super start];isConcurrent是标识这个Operation是否是并发执行的,这里曾经是个坑,如果你没有实现isConcurrent,默认 是返回NO,那么你的NSOperation就不是并发执行而是串行执行的,不过在iOS5.0和OS X10.6之后,已经会默认忽略这个返回值,最终和Queue的maxConcurrentOperationCount最大并发操作值相 关;isExecuting和isFinished是用来报告当前的工作执行状态情况的,注意必须是线程访问安全的。

注意你的实现要发出合适的KVO通知,因为如果你的NSOperation实现需要用到工作依赖从属特性,而你的实现里没有发出合适的“isFinished”KVO通知,依赖你的NSOperation就无法正常执行。NSOperation支持KVO的属性有:

  • isCancelled

  • isConcurrent

  • isExecuting

  • isFinished

  • isReady

  • dependencies

  • queuePriority

  • completionBlock

当然也不是说所有的KVO通知都需要自己去实现,例如通常你用不到addObserver到你工作的“isCancelled”属性,你只需要直接调用cancel方法就可以取消这个工作任务。

实现NSOperation子类后,可以直接调用start或者添加到一个NSOperationQueue里:

NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:downloader];

NSOperation和NSOperationQueue其他特性

工作是有优先级的,可以通过NSOperation的一下两个接口读取或者设置:

- (NSOperationQueuePriority)queuePriority;
- (void)setQueuePriority:(NSOperationQueuePriority)p;

工作之间也可有从属依赖关系,只有依赖的工作完成后才会执行:

- (void)addDependency:(NSOperation *)op;
- (void)removeDependency:(NSOperation *)op;

还可以通过下面接口设置运行NSOpration的子线程优先级:

- (void)setQueuePriority:(NSOperationQueuePriority)priority;

如果要设置Queue的并发操作数:

- (void)setMaxConcurrentOperationCount:(NSInteger)cnt;

iOS4之后还可以往NSOperation上添加一个结束block,用于在工作执行结束之后的操作:

- (void)setCompletionBlock:(void (^)(void))block;

如果需要阻塞等待NSOperation工作结束(别在主线程这么干),可以使用接口:

- (void)waitUntilFinished;

NSOperationQueue除了添加NSOperation外,也支持直接添加一个Block(iOS4之后):

- (void)addOperationWithBlock:(void (^)(void))block

NSOperationQueue可以取消所有添加的工作:

- (void)cancelAllOperations;

也可以阻塞式的等待所有工作结束(别在主线程这么干):

- (void)waitUntilAllOperationsAreFinished;

在NSOperation对象中获得被添加的NSOperationQueue队列:

+ (id)currentQueue

要获得一个绑定在主线程的NSOperationQueue队列:

+ (id)mainQueue

还有些接口参考头文件NSOperation.h和NSOperation Class Reference,Apple的Class Reference文档描述还是很清晰的。

NSInvocationOperation & NSBlockOperation

其实除非必要,简单的工作完全可以使用官方提供的NSOperation两个子类NSInvocationOperation和NSBlockOperation来实现。

NSInvocationOperation:

NSInvocationOperation* theOp = [[NSInvocationOperation alloc] 
                       initWithTarget:self                 
                           selector:@selector(myTaskMethod:)                            
                               object:data];

NSBlockOperation:    

        

NSBlockOperation* theOp = [NSBlockOperation blockOperationWithBlock: ^{      
    NSLog(@"Beginning operation.\n");      
    // Do some work.  
}];

接口非常简单,一看便会。


本文转载自:http://www.hrchen.com/2013/06/multi-threading-programming-of-ios-part-2/

小春0618
粉丝 8
博文 40
码字总数 10552
作品 0
海淀
程序员
私信 提问
iOS之[多线程:NSOperation]

NSOperation :fa-exclamation-triangle:以下是你需要考虑使用 NSOperation 的一些理由: 1.当你需要取消线程任务时,GCD 无法提供取消任务的操作。而 NSOperation 提供了取消任务的操作; 2.当...

言筱羽
2015/11/23
120
0
iOS多线程之NSOperation

1.简介 1.1NSOperation的作用 配合使用NSOperation和NSOperationQueue也能实现多线程编程 1.2NSOperation和NSOperationQueue实现多线程的具体步骤 先将需要执行的操作封装到一个NSOperation...

JlongTian
2016/01/10
34
0
【iOS】多线程NSOperation

NSOperation是苹果封装的一套多线程的东西,不像GCD是纯C语言的,这个是OC的。但相比较之下GCD会更快一些,但本质上NSOPeration是多GDC的封装。 一、NSOperation与GCD的比较 GCD是基于c的底层...

xn4545945
2014/07/28
0
0
NSOperationQueue

NSOperation的作用配合使用NSOperation和NSOperationQueue也能实现多线程编程 NSOperation和NSOperationQueue实现多线程的具体步骤先将需要执行的操作封装到一个NSOperation对象中然后将NSO...

5vinsEnt
2016/05/25
11
0
iOS多线程:『NSOperation、NSOperationQueue』详尽总结

iOS多线程:『NSOperation、NSOperationQueue』详尽总结 转载: 原地址https://www.jianshu.com/p/4b1d77054b35 本文首发于我的个人博客:『不羁阁』 文章链接:传送门 本文更新时间:2018年0...

法斗斗
2018/04/20
12
0

没有更多内容

加载失败,请刷新页面

加载更多

总结

一、设计模式 简单工厂:一个简单而且比较杂的工厂,可以创建任何对象给你 复杂工厂:先创建一种基础类型的工厂接口,然后各自集成实现这个接口,但是每个工厂都是这个基础类的扩展分类,spr...

BobwithB
51分钟前
4
0
java内存模型

前言 Java作为一种面向对象的,跨平台语言,其对象、内存等一直是比较难的知识点。而且很多概念的名称看起来又那么相似,很多人会傻傻分不清楚。比如本文我们要讨论的JVM内存结构、Java内存模...

ls_cherish
54分钟前
4
0
友元函数强制转换

友元函数强制转换 p522

天王盖地虎626
昨天
5
0
js中实现页面跳转(返回前一页、后一页)

本文转载于:专业的前端网站➸js中实现页面跳转(返回前一页、后一页) 一:JS 重载页面,本地刷新,返回上一页 复制代码代码如下: <a href="javascript:history.go(-1)">返回上一页</a> <a h...

前端老手
昨天
5
0
JAVA 利用时间戳来判断TOKEN是否过期

import java.time.Instant;import java.time.LocalDateTime;import java.time.ZoneId;import java.time.ZoneOffset;import java.time.format.DateTimeFormatter;/** * @descri......

huangkejie
昨天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部