多线程学习笔记3-NSOperationQueue

NSOperationQueue

  • NSOperation的作用
    • 配合使用NSOperation和NSOperationQueue也能实现多线程编程
  • NSOperation和NSOperationQueue实现多线程的具体步骤
    • 先将需要执行的操作封装到到一个NSOperation对象中
    • 然后将NSOperation对象添加到NSOperationQueue中
    • 系统会自动将 NSOperationQueue中的NSOperation取出来

NSOperation的子类

  • NSOperation是个抽象类,布局类封装操作的能力,必须使用它的子类
  • 使用NSOperation子类的方式有3种
    • NSInvocationOperation
    • NSBlockOperation
    • 自定义子类继承NSOperation,实现内部相应的方法

NSInvocationOperation

  • 创建NSInvocationOperation对象
    -(id)initWithTarget:(id)target selector:(SEL)sel object:(id)arg;
  • 调用start方法开始执行操作
    • -(void)start;
    • 一旦执行操作,就会调用target的sel方法
  • 注意
    • 默认情况下,调用了start方法后并不会开一条新线程去执行操作,而是在当前线程同步执行操作
    • 只有将 NSOperation放到一个NSOperationQueue中,才会异步执行操作

NSBlockOperation

  • 创建NSBlockOperation对象
    +(id)blockOperationWithBlock:(void(^)(void))block;
  • 通过addExecutionBlock方法添加更多的操作
    -(void)addExecutionBlock:(void(^)(void))block;
  • 注意:只要NSBlockOperation封装的操作数>1,就会异步执行操作

自定义子类继承NSOperation

  • 步骤:重写-(void)main方法,在里面实现想执行的任务
  • 可以选择实现is current等函数
  • 重写-(void)main方法的注意点
    • 自己创建自动释放池(因为如果是异步操作,无法访问主线程的自动释放池)
    • 经常通过-(BOOL)isCancelled方法检测操作是否被取消,对取消作出响应

NSOperationQueue的使用

  • 作用:NSOperation可以调用start方法来执行任务,但默认是同步执行的,如果NSOperation添加到NSOperationQueue(操作队列)中,系统会自动异步执行NSOperation中的操作
  • NSOperationQueue的队列类型
    • 主队列
      • [NSOperationQueue mainQueue]
      • 凡是添加到主队列中的任务(NSOperation),都会放到主线程中执行
    • 非主队列/ 其他队列(串行、并发)
      • [[NSOperationQueue alloc]init]
      • 同时包含了串行、并发功能
      • 添加到这种队列中的任务(NSOperation),就会自动放到子线程中执行
  • 可以直接把任务加进去
    [queue addOperationWithBlock:(void(^)(void))block
  • maxConcurrentOperationCount参数值,用于控制最大并发数。默认值是-1。当这个值为1时,就变成了串行。如果为0,表示没有并发数,即任务都不会执行
  • suspended。暂停/挂起。该属性为YES,表示暂停/挂起;该属性为NO,任务继续执行
  • 取消所有操作 [queue cancelAllOperations];相当于调用了当前所有operation的cancel方法
  • 注意:无论是暂停还是取消,针对的都是整个任务,都是在当前任务执行完毕后才会暂停或取消
  • 操作依赖。
    • [op3 addDependency:op1];意味着op1执行完毕,才能执行op3
    • NSOperation之间可以设置依赖来保证执行顺序
    • 可以在不同queue的NSOperation之间创建依赖关系
    • 注意:不能相互依赖。比如A依赖B,B依赖A
  • 操作的监听
    • 可以监听一个操作的执行完毕
      -(void)(^)(void))completionBlock;
      -(void)setCompletionBlock:(void)(^)void))block;

线程间的通讯

  • 示例代码
 [[[NSOperationQueue alloc]init] addOperationWithBlock:^{
        NSURL *url = [NSURL URLWithString:@"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1503992696462&di=e51b985b9790aceef17d1d8e80f9c4b8&imgtype=0&src=http%3A%2F%2Fimglf0.ph.126.net%2F1EnYPI5Vzo2fCkyy2GsJKg%3D%3D%2F2829667940890114965.jpg"];
        NSData *data = [NSData dataWithContentsOfURL:url];
        UIImage *image = [UIImage imageWithData:data];
    [[NSOperationQueue mainQueue]addOperationWithBlock:^{
        self.imageView.image = image;
    }];
    }];
  • 在子线程下载图片,下载完成后回到主线程
    __block UIImage *image1 = nil;//为了防止整个大括号代码走完,image1还没用完,就加个__block,防止销毁
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    //下载图片1
    NSBlockOperation *download1 = [NSBlockOperation blockOperationWithBlock:^{

    }];
    __block UIImage *image2 = nil;
    //下载图片2
    NSBlockOperation *download2 = [NSBlockOperation blockOperationWithBlock:^{

    }];
    //合并图片
    NSBlockOperation *combine = [NSBlockOperation blockOperationWithBlock:^{
        //合并完后,可以给iamge12赋值为nil,进行销毁
        //回到主线程
        [[NSOperationQueue mainQueue]addOperationWithBlock:^{

        }];
    }];
    [combine addDependency:download1];
    [combine addDependency:download2];

    [queue addOperation:download1];
    [queue addOperation:download2];
    [queue addOperation:combine];

多图片下载

  • 自定义NSOperation下载图片思路-有沙盒缓存
    这里写图片描述

  • 示例代码

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"app"];
    XXApps *app = self.appArray[indexPath.row];
    cell.textLabel.text = app.name;
    cell.detailTextLabel.text = app.download;

    UIImage *image = self.imageCache[app.icon];
    if (image) {
        cell.imageView.image = image;
    }else{
        NSString *cachesPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)lastObject];
        NSString *fileName = [app.icon lastPathComponent];
        NSString *file = [cachesPath stringByAppendingPathComponent:fileName];
        NSData *data = [NSData dataWithContentsOfFile:file];
        if (data) {
            UIImage *image = [UIImage imageWithData:data];
            cell.imageView.image = image;
            self.imageCache[app.icon] = image;
        }else{//下载图片
            cell.imageView.image = [UIImage imageNamed:@"阿狸头像"];
            NSOperation *op = self.operations[app.icon];
            if (op == nil) {//这张图片暂时没有下载任务
                op = [NSBlockOperation blockOperationWithBlock:^{
                   //下载图片
                    NSURL *url = [NSURL URLWithString:app.icon];
                    NSData *data = [NSData dataWithContentsOfURL:url];
                  //数据加载失败
                    if (data == nil){
                        //移除操作
                        [self.operations removeObjectForKey:app.icon];
                        return;
                    }
                    UIImage *image = [UIImage imageWithData:data];

                     //存到字典中
                    self.imageCache[app.icon] = image;     
                    //回到主线程显示图片
                    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                        [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
                    }];
                  //将图片文件数据写入到沙盒中
                    [data writeToFile:file atomically:YES];
                   //移除操作
                    [self.operations removeObjectForKey:app.icon];
                }];

                //添加到队列中
                self.operations[app.icon] = op;

                //存放到字典中
                [self.queue addOperation:op];
            }

            NSLog(@"%@",file);
//            NSDictionary *dic = @{
//                                  file:[NSDate date]
//                                  };
        }

        NSLog(@"%@",file);

    }
    //获取文件属性
//    [NSFileManager defaultManager]attributesOfItemAtPath:<#(nonnull NSString *)#> error:<#(NSError * _Nullable __autoreleasing * _Nullable)#>
return cell;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值