NSOperation备忘

转载请注明出处:http://www.cnblogs.com/idalink/articles/4438367.html

1、操作的元NSOperation

在GCD中,一个block任务代表一个计算任务。在NSOperation中,一个NSOperation对象代表一个计算任务。NSOperation的子类有NSInvocationOperationNSBlockOperation,分别代表一个传统Objc消息结构元和block块元。

2、NSOperation的用法

调用NSOperation的start方法即可启动任务。该任务同步同线程启动。

- (void)viewDidLoad
{
    NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(startOperation) object:nil];
    
    [operation start];
    NSLog(@"viewDidLoad %@", [NSThread currentThread]);
}

- (void)startOperation
{
    [NSThread sleepForTimeInterval:2];
    NSLog(@"startOperation %@", [NSThread currentThread]);
}
2015-04-18 23:03:43.852 test_operationqueue[1329:56498] startOperation <NSThread: 0x78849010>{number = 1, name = main}
2015-04-18 23:03:43.853 test_operationqueue[1329:56498] viewDidLoad <NSThread: 0x78849010>{number = 1, name = main}

3、NSOperationQueue

同步启动NSOperation肯定不是线程管理的需求。NSOperationQueue用以管理NSOperation的执行。

调用以下方法可以把NSOperation加入到任务中。这些任务将会异步并发执行。

- (void)addOperation:(NSOperation *)op;

也可以使用以下方法获取NSOperation:

@property (readonly, copy) NSArray *operations;

也可以使用以下方法移除NSOperation:

//NSOperation
- (void)cancel;

//NSOperationQueue
- (void)cancelAllOperations;

 

4、依赖设置

一个NSOperation可以依赖另外一个NSOperation任务,无论这些任务是否在同一个NSOperationQueue中。如果一个任务A被设置为依赖任务B,那么只有B被执行完毕才会执行A。并且A和B会在同一个线程中执行,这体现了NSoperationQueue强大的线程资源管理机制。

- (void)viewDidLoad
{
    NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(startOperation) object:nil];
    NSInvocationOperation *operation2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(startOperation) object:nil];
    [operation addDependency:operation2];
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    [queue addOperation:operation];
    NSOperationQueue *queue2 = [[NSOperationQueue alloc] init];
    [queue2 addOperation:operation2];
    NSLog(@"viewDidLoad %@", [NSThread currentThread]);
}

- (void)startOperation
{
    [NSThread sleepForTimeInterval:2];
    NSLog(@"startOperation %@", [NSThread currentThread]);
}
2015-04-18 23:14:19.211 test_operationqueue[1470:61940] viewDidLoad <NSThread: 0x7ae883f0>{number = 1, name = main}
2015-04-18 23:14:21.215 test_operationqueue[1470:61989] startOperation <NSThread: 0x7c889a00>{number = 2, name = (null)}
2015-04-18 23:14:23.221 test_operationqueue[1470:61989] startOperation <NSThread: 0x7c889a00>{number = 2, name = (null)}

 5、优先级设定

添加到NSOperationQueue的任务总是并发执行,这些对象都拥有NSOperationQueuePriorityNormal优先级。如果把任务设定优先级,则会影响任务的执行顺序。需要注意的是,优先级不会跨越NSOperationQueue。其次,优先级无法改变依赖条件。只有先满足依赖条件,才由优先级影响调用顺序。

- (void)viewDidLoad
{
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    
    NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^(){
        NSLog(@"第一个NSBlockOperation %@", [NSThread currentThread]);
    }];
    
    NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^(){
        NSLog(@"第二个NSBlockOperation %@", [NSThread currentThread]);
    }];
    
    [queue addOperation:operation1];
    [queue addOperation:operation2];
    
    [operation1 setQueuePriority:NSOperationQueuePriorityHigh];
}
2015-04-18 23:20:59.551 test_operationqueue[1598:65637] 第二个NSBlockOperation <NSThread: 0x7b67d2d0>{number = 3, name = (null)}
2015-04-18 23:20:59.551 test_operationqueue[1598:65636] 第一个NSBlockOperation <NSThread: 0x7b7361f0>{number = 2, name = (null)}

6、并发限制

添加到NSOperationQueue的任务总是并发执行,如果添加的任务过多,则开辟的线程就会过多。我们可以设定NSOperationQueue的最大并发数,则开辟的线程不超过最大并发数。

设置最大并发数通过下面消息设定。

@property NSInteger maxConcurrentOperationCount;

 

需要注意的是设定并发数的个数,不能少于当前的任务数,否则已经添加过的任务继续并发,不受最大并发数的影响,但是以后的任务依然受最大并发数的影响。其次NSOperationQueue会自动复用线程。

Demo 证明最大并发数不影响已经添加的任务:

- (void)viewDidLoad
{
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    
    NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^(){
        [NSThread sleepForTimeInterval:2];
        NSLog(@"第一个NSBlockOperation %@", [NSThread currentThread]);
    }];
    
    NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^(){
        [NSThread sleepForTimeInterval:2];
        NSLog(@"第二个NSBlockOperation %@", [NSThread currentThread]);
    }];
    
    NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^(){
        [NSThread sleepForTimeInterval:2];
        NSLog(@"第三个NSBlockOperation %@", [NSThread currentThread]);
    }];
    
    NSBlockOperation *operation4 = [NSBlockOperation blockOperationWithBlock:^(){
        [NSThread sleepForTimeInterval:2];
        NSLog(@"第四个NSBlockOperation %@", [NSThread currentThread]);
    }];
    
    [queue addOperation:operation1];
    [queue addOperation:operation2];
    [queue setMaxConcurrentOperationCount:1];
    [queue addOperation:operation3];
    [queue addOperation:operation4];
    
}
2015-04-18 23:33:57.186 test_operationqueue[1820:72896] 第二个NSBlockOperation <NSThread: 0x78845c90>{number = 2, name = (null)}
2015-04-18 23:33:57.186 test_operationqueue[1820:72898] 第一个NSBlockOperation <NSThread: 0x7864a670>{number = 3, name = (null)}
2015-04-18 23:33:59.190 test_operationqueue[1820:72897] 第三个NSBlockOperation <NSThread: 0x7884c4a0>{number = 4, name = (null)}
2015-04-18 23:34:01.194 test_operationqueue[1820:72896] 第四个NSBlockOperation <NSThread: 0x78845c90>{number = 2, name = (null)}

Demo证明NSOperationQueue的线程复用:

- (void)viewDidLoad
{
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    
    NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^(){
        [NSThread sleepForTimeInterval:2];
        NSLog(@"第一个NSBlockOperation %@", [NSThread currentThread]);
    }];
    
    NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^(){
        [NSThread sleepForTimeInterval:2];
        NSLog(@"第二个NSBlockOperation %@", [NSThread currentThread]);
    }];
    
    NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^(){
        [NSThread sleepForTimeInterval:2];
        NSLog(@"第三个NSBlockOperation %@", [NSThread currentThread]);
    }];
    
    NSBlockOperation *operation4 = [NSBlockOperation blockOperationWithBlock:^(){
        [NSThread sleepForTimeInterval:2];
        NSLog(@"第四个NSBlockOperation %@", [NSThread currentThread]);
    }];
    
    [queue setMaxConcurrentOperationCount:1];
    [queue addOperation:operation1];
    [queue addOperation:operation2];
    [queue addOperation:operation3];
    [queue addOperation:operation4];
    
}
2015-04-18 23:34:40.909 test_operationqueue[1841:73486] 第一个NSBlockOperation <NSThread: 0x7b871bb0>{number = 2, name = (null)}
2015-04-18 23:34:42.911 test_operationqueue[1841:73493] 第二个NSBlockOperation <NSThread: 0x7b95d030>{number = 3, name = (null)}
2015-04-18 23:34:44.913 test_operationqueue[1841:73486] 第三个NSBlockOperation <NSThread: 0x7b871bb0>{number = 2, name = (null)}
2015-04-18 23:34:46.914 test_operationqueue[1841:73493] 第四个NSBlockOperation <NSThread: 0x7b95d030>{number = 3, name = (null)}

7、等待NSOperation和NSOperationQueue的任务完成

 NSOperation的等待消息原型:

- (void)waitUntilFinished NS_AVAILABLE(10_6, 4_0);

NSOperationQueue的等待消息原型:

- (void)waitUntilAllOperationsAreFinished;

8、NSOperationQueue的暂停和继续

@property (getter=isSuspended) BOOL suspended;

 

posted @ 2015-04-18 23:47  Dalink  阅读(164)  评论(0编辑  收藏  举报