OC高级-NSOperation 和 NSOperationQu

2016-08-25  本文已影响273人  yanhooIT

实现多线程的具体步骤

NSOperation

NSInvocationOperation

- (id)initWithTarget:(id)target selector:(SEL)sel object:(id)arg;
- (void)invocationOperation
{
    NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil];

    // 调用start方法
    [op start];
}

- (void)run
{
    NSLog(@"------%@", [NSThread currentThread]);
}

NSBlockOperation

+ (id)blockOperationWithBlock:(void (^)(void))block;
- (void)addExecutionBlock:(void (^)(void))block;
- (void)blockOperation
{
    NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^
    {
        // 这个任务是在【主线程】
        NSLog(@"下载1------%@", [NSThread currentThread]);
    }];

    // 添加额外的任务(在子线程执行)
    [op addExecutionBlock:^{
        NSLog(@"下载2------%@", [NSThread currentThread]);
    }];
    [op addExecutionBlock:^{
        NSLog(@"下载3------%@", [NSThread currentThread]);
    }];
    [op addExecutionBlock:^{
        NSLog(@"下载4------%@", [NSThread currentThread]);
    }];

    [op start];
}

自定义继承自NSOperation的操作

- (void)main
{
    @autoreleasepool
    {
        for (NSInteger i = 0; i < 1000; i++)
        {
            NSLog(@"download1 -%zd-- %@", i, [NSThread currentThread]);
        }

        // 由于任务一旦开始执行就没办法停止下来
        // 苹果官方建议,如果是自定义的Operation,而且内部的执行逻辑很耗时
        // 如果外面调用了cancel方法,可以通过在一段耗时逻辑后调用一次isCancelled方法判断操作是否已经取消,以用来中断任务的执行
        
        // 合理布局此方法
        if (self.isCancelled) return;

        for (NSInteger i = 0; i< 1000; i++)
        {
            NSLog(@"download2 -%zd-- %@", i, [NSThread currentThread]);
        }

        if (self.isCancelled) return;

        for (NSInteger i = 0; i < 1000; i++)
        {
            NSLog(@"download3 -%zd-- %@", i, [NSThread currentThread]);
        }

        if (self.isCancelled) return;
    }
}

NSOperation设置依赖

// 操作B依赖于操作A
[operationB addDependency:operationA];
- (void)addDependencyTest
{
    // 直接创建
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];

    NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"download1----%@", [NSThread  currentThread]);
    }];
    NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"download2----%@", [NSThread  currentThread]);
    }];
    NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"download3----%@", [NSThread  currentThread]);
    }];

    // 设置依赖后再添加到队列
    // 当op1和op2都执行完才执行op3,但是op1和op2谁先执行完不确定
    [op3 addDependency:op1];
    [op3 addDependency:op2];

    // 【不能】循环依赖
    //    [op3 addDependency:op1];
    //    [op1 addDependency:op3];

    [queue addOperation:op1];
    [queue addOperation:op2];
    [queue addOperation:op3];
}
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^
{
    NSLog(@"download----%@", [NSThread  currentThread]);
}];

// 任务执行完毕就会执行这个block
op.completionBlock = ^
{
    // 也是在子线程中执行
    NSLog(@"op执行完毕后执行---%@", [NSThread currentThread]);
};

NSOperationQueue

添加操作到NSOperationQueue中方法

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

// 推荐使用此种方式添加任务
- (void)addOperationWithBlock:(void (^)(void))block;

最大并发数

// 调用示例
queue.maxConcurrentOperationCount = 1;

暂停和恢复队列:suspended

// 调用示例
queue.suspended = !self.queue.suspended;

取消队列的所有操作:cancelAllOperations

// 调用示例
[queue cancelAllOperations];

线程间通信

- (void)test
{
    [[[NSOperationQueue alloc] init] addOperationWithBlock:^
    {
        // 图片的网络路径
        NSURL *url = [NSURL URLWithString:@"http://img.pconline.com.cn/images/photoblog/9/9/8/1/9981681/200910/11/1255259355826.jpg"];

        // 加载图片
        NSData *data = [NSData dataWithContentsOfURL:url];

        // 生成图片
        UIImage *image = [UIImage imageWithData:data];

        // 回到主线程
        [[NSOperationQueue mainQueue] addOperationWithBlock:^
        {
            self.imageView.image = image;
        }];
    }];
}

GCD的队列和NSOperationQueue队列对比

GCD的队列

NSOperationQueue队列类型

上一篇 下一篇

猜你喜欢

热点阅读