NSOperation基本使用

 NSOperation简单介绍

a. 是OC语言中基于GCD的面向对象的封装

b. 使用起来比GCD更加简单(面向对象)

c. 提供了一些用GCD不好实现的功能

d. 苹果推荐使用,使用NSOperation不用关心线程以及线程的生命周期



1. NSOperation是一个抽象类

i. 不能直接使用(方法没有实现)

ii. 约束子类都具有共同的属性和方法



2. NSOperation的子类

i. NSInvocationOperation

ii. NSBlockOperation

 

3.NSOperationQueue 队列

 

 

NSInvocationOperation代码演示

1. 执行操作

    //创建操作

    NSInvocationOperation* op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadFile:) object:@"fileName"];

    //在当前线程执行方法(开始执行操作)

    [op start];

 

2. 把操作添加到队列(并开始异步执行) //创建操作

    NSInvocationOperation* op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadFile:) object:@"fileName"];

 

        //将操作添加到队列,会自动异步调用方法

        NSOperationQueue *queue = [[NSOperationQueue alloc] init];

 

        [queue addOperation:op];

 

- (void)downloadFile:(id)object { NSLog(@"下载:%@----线程:%@", object, [NSThread currentThread]); }

 

3. 开启多个线程, 不会顺序执行-- -》GCD并发队列, 异步执行

    //队列

    NSOperationQueue* queue = [[NSOperationQueue alloc] init];

    for (int i = 0; i < 10; i++) {

    //创建操作

    NSInvocationOperation* op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadFile:) object:@(i)];

    //将操作添加到队列,会自动异步调用方法

    [queue addOperation:op];

}

 

- (void)downloadFile:(id)object

{

    NSLog(@"下载:%@----线程:%@", object, [NSThread currentThread]);

 

 

NSBlockOperation代码演示

//1. NSBlockOperation

//队列

NSOperationQueue* queue = [[NSOperationQueue alloc] init];

for (int i = 0; i < 10; i++) { //操作

    NSBlockOperation* op = [NSBlockOperation blockOperationWithBlock:^{

        NSLog(@"down %d %@", i, [NSThread currentThread]);

    }];

    [queue addOperation:op];

}

 

//2. NSOperationQueue添加block的operation代码更简练

NSOperationQueue* queue = [[NSOperationQueue alloc] init];

for (int i = 0; i < 10; i++) {

    [queue addOperationWithBlock:^{

        NSLog(@"down %d %@", i, [NSThread currentThread]);

    }];

}

//3. 全局操作队列(controller的全局), 调度所有的异步操作 定义属性

@property (nonatomic, strong) NSOperationQueue* queue;

//懒加载队列

- (NSOperationQueue*)queue

{

    if (_queue == nil) {

        _queue = [[NSOperationQueue alloc] init];

    }

    return _queue;

}

for (int i = 0; i < 10; i++) {

    [self.queue addOperationWithBlock:^{

        NSLog(@"down %d %@", i, [NSThread currentThread]);

    }];

}

//4. 监听操作完成

[op1 setCompletionBlock:^{

    NSLog(@".....");

}];

 

 

线程间通讯

//1. 主队列 添加到主队列的操作,最终都执行在主线程上

[NSOperationQueue mainQueue]

     //获取当前操作所在的队列

    [NSOperationQueue currentQueue]

    [self.queue addOperationWithBlock:^{

        NSLog(@"异步执行的 %@", [NSThread currentThread]);

         //获取主队列

        [[NSOperationQueue mainQueue] addOperationWithBlock:^{

            NSLog(@"主线程?%@", [NSThread currentThread]);

            //当前队列是谁呢? 正在执行操作的队列

            [[NSOperationQueue currentQueue] addOperationWithBlock:^{

                NSLog(@"当前队列是谁呢 %@", [NSThread currentThread]);

            }];

        }];

    }];

 

 

NSOperation中的方便的使用 

1. 最大并发数

self.queue.maxConcurrentOperationCount = 2;

for (int i = 0; i < 20; i++) {

    [self.queue addOperationWithBlock:^{ //加上此代码后执行的过程?

        [NSThread sleepForTimeInterval:1];

        NSLog(@"%@---%d", [NSThread currentThread], i);

    }];

}

• 执行过程

1、把操作添加到队列 self.queue addOperationWithBlock

2、去线程池去取空闲的线程, 如果没有就创建线程

3、把操作交给从线程池中取出的线程执行

4、执行完成后, 把线程再放回线程池中

5、重复2, 3, 4知道所有的操作都执行完

 


2. 队列的暂定/继续 取消

1. 暂停 判断队列是否是挂起状态时, 并不会判断队列中是否有操作 我们可以先判断下队列是否为空
if (self.queue.operationCount == 0)
{
    NSLog(@"队列中没有操作");
    return;
}
2. 继续 - (IBAction)pause
{
    if (self.queue.operationCount == 0) {
        NSLog(@"队列中没有操作");
        return;
    }
    if (self.queue.isSuspended) { //继续
        self.queue.suspended = NO;
        NSLog(@"继续");
    }
    else {
        //挂起(暂定)
        self.queue.suspended = YES; NSLog(@"暂停");
    }
    //当前队列的操作数
    NSLog(@"%lu", self.queue.operationCount);
}
3. 取消(清除队列中的操作) - (IBAction)cancel
{
    [self.queue cancelAllOperations];
    NSLog(@"取消");
    NSLog(@"%lu", self.queue.operationCount);
}
4. 等待队列中的操作执行完毕
//等待队列中的操作执行完毕,会阻塞
[self.queue waitUntilAllOperationsAreFinished]; NSLog(@"over");

 

依赖关系 

1. 模拟软件的部分升级
//依赖关系
//模拟软件的部分升级
//下载压缩包
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
                         NSLog(@"下载 %@",[NSThread currentThread]); }];
//解压,复制到相应目录
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
                         NSLog(@"解压 %@",[NSThread currentThread]); }];
//通知用户
NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
                         NSLog(@"通知用户升级完成 %@",[NSThread currentThread]); }];
//设置操作的依赖关系
[op2 addDependency:op1];
[op3 addDependency:op2];
//添加操作
//waitUntilFinished YES 等待所有的操作执行完成 会阻塞窗体的执行 //waitUntilFinished NO 不等待
[self.queue addOperations:@[op1,op2,op3] waitUntilFinished:NO]; NSLog(@"over");

2. 循环依赖 发生循环依赖,程序不会死锁。界面也不会阻塞,操作不会执行 [op2 addDependency:op1];
[op3 addDependency:op2];
[op1 addDependency:op3]; 3. 依赖关系可以快队列执行
//设置操作的依赖关系 [op2 addDependency:op1]; [op3 addDependency:op2];
[self.queue addOperations:@[op1,op2] waitUntilFinished:NO]; NSLog(@"over");
[[NSOperationQueue mainQueue] addOperation:op3];

 

posted on 2015-09-04 23:57  lizzie8023  阅读(116)  评论(0编辑  收藏  举报