多线程-GCD、NSOPeration

作者: 光明程辉 | 来源:发表于2016-02-22 23:02 被阅读40次

    1、 多线程 --生命周期:新建、就绪、运行、组赛、死亡

    //  在多线程中使用定时器必须开启Runloop.
      [[NSRunLoop currentRunLoop] run];
    

    1.NSThread
    1> 开线程的几种方式

    • 先创建,后启动
      NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
      [thread start];

    • 直接启动
      [NSThread detachNewThreadSelector:@selector(run) toTarget:self withObject:nil];
      [self performSelectorInBackground:@selector(run) withObject:nil];

    2、其他用法

      NSThread *current = [NSThread currentThread];
      + (NSThread *)mainThread; // 获得主线程
    

    3 线程间通信
    performSelectorOnMainThread.....

    什么情况下选择GCD,和 NSOperationQueue呢? 依赖强选择后者。

    -2.GCD(重点--把任务(线程)添加到队列里)
    1> 队列的类型
    //* 并发队列
    获得全局的并发队列: dispatch_get_global_queue

    //* 串行队列
    a.自己创建
    dispatch_queue_create

    b.主队列
    dispatch_get_main_queue

    2> 执行任务的方法类型

    • 同步(sync)执行
    • 异步(async)执行

    3> 了解队列和方法的配合使用

    4> 线程间通信

    dispatch_async(
    dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
     // 执行耗时的异步操作...(全局队列,由系统自动调用,在子线程中调用)
    
     dispatch_async(dispatch_get_main_queue(), ^{
       // 回到主线程,执行UI刷新操作
       });
    });
    

    5> 其他用法
    dispatch_once
    dispatch_after
    dispatch_group_async\dispatch_group_notify

    3.NSOperation
    1> 基本使用
    NSInvocationOperation
    NSBlockOperation

    // 2> NSOperationQueue(重点)

    • 最大并发数设置
    • (void)setMaxConcurrentOperationCount:(NSInteger)cnt;
    • 设置依赖(面试题)
      [operationB addDependency:operationA]; // 操作B依赖于操作A

    3> 如何解决一张图片(一个url)重复下载的问题?

    // 答:利用Operation缓存操作,(key值 ,URL)根据图片的URL去images中取得图片,判断是否存在,存在直接显示,否则,显示占位图片,然后根据图片的URL去查看operation中是否存在下载操作,存在,则下载,否则创建下载操作,下载后放到images文件中保存

    4、 自定义Operation(基本流程)

    • 自定义方法的步骤:
    • 1、重写main方法,自己创建自动释放池(因为异步操作,无法访问主线程的自动释放池)
    • 2、在main方法中实现具体操作

    // 重写- (void)main方法的注意点
    // 自己创建自动释放池(因为如果是异步操作,无法访问主线程的自动释放池)
    // 经常通过- (BOOL)isCancelled方法检测操作是否被取消,对取消做出响应

    - (void)main
    {
    @autoreleasepool {
        //  正规写法,经常检查操作是否被取消,必须判断
        if (self.isCancelled) return;
        
        NSURL *downloadUrl = [NSURL URLWithString:self.url];
        NSData *data = [NSData dataWithContentsOfURL:downloadUrl]; // 这行会比较耗时
        
        if (self.isCancelled) return;
        
        UIImage *image = [UIImage imageWithData:data];
        
        if (self.isCancelled) return;
        if ([self.delegate respondsToSelector:@selector(downloadOperation:didFinishDownload:)]) {
            dispatch_async(dispatch_get_main_queue(), ^{ // 回到主线程, 传递图片数据给代理对象
                [self.delegate downloadOperation:self didFinishDownload:image];
            });
        }
    }
    

    bolck 的使用?

    • 声明一个block
      1> @property (nonatomic, copy) void (testBlock^)(); // 使用 copy

      // 1.如果没有对block进行copy操作,block就存储于 [栈空间](指针)
      // 2.如果对block进行copy操作,block就存储于 [堆空间](app管理)

      // 3.如果block存储于栈空间,不会对block内部所用到的对象产生强引用
      // 4.如果block存储于堆空间,就会对block内部所用到的对象产生强引用
      Person *p = [[Person alloc]init];
      __weak typeof(p) weakP = p;
      p.testBlock = ^ {
      [weakP run]; // 强引用
      };

      2> block
      (1)、block的内存管理
      (2)、防止循环(retain)ARC :__weak , 非ARC __block

    不多说:GCD 意外惊喜

    相关文章

      网友评论

      本文标题:多线程-GCD、NSOPeration

      本文链接:https://www.haomeiwen.com/subject/koubkttx.html