iOS多线程编程Part 2/3 - NSOperation

转自出处:http://www.hrchen.com/2013/06/multi-threading-programming-of-ios-part-2/


iOS多线程编程Part 2/3 - NSOperation

多线程编程Part 1介绍了NSThread以及NSRunLoop,这篇Blog介绍另一种并发编程技术:NSOPeration。

NSOperation & NSOperationQueue

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

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

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

1
2
3
4
5
6
7
8
9
10
11
-(void)main 
{
   @try 
   {
      // 处理工作任务
   }
   @catch(...) 
   {
      // 处理异常,但是不能再重新抛出异常
   }
}

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

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

  • start
  • isConcurrent
  • isExecuting
  • isFinished

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
- (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里:

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

NSOperation和NSOperationQueue其他特性

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

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

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

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

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

1
- (void)setQueuePriority:(NSOperationQueuePriority)priority;

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

1
- (void)setMaxConcurrentOperationCount:(NSInteger)cnt;

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

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

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

1
- (void)waitUntilFinished;

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

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

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

1
- (void)cancelAllOperations;

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

1
- (void)waitUntilAllOperationsAreFinished;

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

1
+ (id)currentQueue

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

1
+ (id)mainQueue

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

NSInvocationOperation & NSBlockOperation

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

NSInvocationOperation:

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

NSBlockOperation:

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

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

Sample Code

本文例子放在Github上(工程NSURLConnectionExample中的PTOperationDownloader)。

参考资料

Concurrency Programming Guide

NSOperation Class Reference


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
旅游社交小程序功能有管理员和用户。管理员有个人中心,用户管理,每日签到管理,景点推荐管理,景点分类管理,防疫查询管理,美食推荐管理,酒店推荐管理,周边推荐管理,分享圈管理,我的收藏管理,系统管理。用户可以在微信小程序上注册登录,进行每日签到,防疫查询,可以在分享圈里面进行分享自己想要分享的内容,查看和收藏景点以及美食的推荐等操作。因而具有一定的实用性。 本站后台采用Java的SSM框架进行后台管理开发,可以在浏览器上登录进行后台数据方面的管理,MySQL作为本地数据库,微信小程序用到了微信开发者工具,充分保证系统的稳定性。系统具有界面清晰、操作简单,功能齐全的特点,使得旅游社交小程序管理工作系统化、规范化。 管理员可以管理用户信息,可以对用户信息添加修改删除。管理员可以对景点推荐信息进行添加修改删除操作。管理员可以对分享圈信息进行添加,修改,删除操作。管理员可以对美食推荐信息进行添加,修改,删除操作。管理员可以对酒店推荐信息进行添加,修改,删除操作。管理员可以对周边推荐信息进行添加,修改,删除操作。 小程序用户是需要注册才可以进行登录的,登录后在首页可以查看相关信息,并且下面导航可以点击到其他功能模块。在小程序里点击我的,会出现关于我的界面,在这里可以修改个人信息,以及可以点击其他功能模块。用户想要把一些信息分享到分享圈的时候,可以点击新增,然后输入自己想要分享的信息就可以进行分享圈的操作。用户可以在景点推荐里面进行收藏和评论等操作。用户可以在美食推荐模块搜索和查看美食推荐的相关信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值