• 【iOS开发-91】GCD的同步异步串行并行、NSOperation和NSOperationQueue一级用dispatch_once实现单例(转载)


    (1)GCD实现的同步异步、串行并行。

    ——同步sync应用场景:用户登录,利用阻塞

    ——串行异步应用场景:下载等耗时间的任务

    /**
     *  因为是异步,所以开通了子线程,但是因为是串行队列,所以只需要开通1个子线程(2),它们在子线程中顺序执行。最常用。
     */
    -(void)gcdDemo1{
      dispatch_queue_t q1=dispatch_queue_create("com.hellocation.gcdDemo", DISPATCH_QUEUE_SERIAL);
      for (int i=0; i<10; i++) {
        dispatch_async(q1, ^{
          NSLog(@"%@",[NSThread currentThread]);
        });
      }
    }
    /**
     *  因为是异步,所以开通了子线程,且因为是并行队列,所以开通了好多个子线程,具体几个,无人知晓,看运气。线程数量无法控制,且浪费。
     */
    -(void)gcdDemo2{
      dispatch_queue_t q2=dispatch_queue_create("com.hellocation.gcdDemo", DISPATCH_QUEUE_CONCURRENT);
      for (int i=0; i<10; i++) {
        dispatch_async(q2, ^{
          NSLog(@"%@",[NSThread currentThread]);
        });
      }
    }
    /**
     *  因为是同步,所以无论是并行队列还是串行队列,都是在主线程中执行
     */
    -(void)gcdDemo3{
      dispatch_queue_t q1=dispatch_queue_create("com.hellocation.gcdDemo", DISPATCH_QUEUE_SERIAL);
      for (int i=0; i<10; i++) {
        dispatch_sync(q1, ^{
          NSLog(@"%@",[NSThread currentThread]);
        });
      }
    }
    /**
     *  全局队列和并行队列类似(全局队列不需要创建直接get即可,而导致其没有名字,不利于后续调试)
     */
    -(void)gcdDemo5{
      dispatch_queue_t q=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
      for (int i=0; i<10; i++) {
        dispatch_sync(q, ^{
          NSLog(@"%@",[NSThread currentThread]);
        });
      }
      for (int i=0; i<10; i++) {
        dispatch_async(q, ^{
          NSLog(@"%@",[NSThread currentThread]);
        });
      }
    }
    /**
     *  因为是主线程,所以异步任务也会在主线程上运行(1)。而如果是同步任务,则阻塞了,因为主线程一直会在运行,所以后米的任务永远不会被执行。
     *  主要用处,是更新UI,更新UI一律在主线程上实现
     */
    -(void)gcdDemo6{
      dispatch_queue_t q=dispatch_get_main_queue();
      for (int i=0; i<10; i++) {
        dispatch_sync(q, ^{
          NSLog(@"%@",[NSThread currentThread]);
        });
      }
    //	for (int i=0; i<10; i++) {
    //		dispatch_async(q, ^{
    //			NSLog(@"%@",[NSThread currentThread]);
    //		});
    //	}
    }
    

    (2)NSOperation和NSOperationQueue实现的线程管理

    /**
     *  1、只要是自己创建的队列,添加进来的操作(此处是block操作),都在子线程上(2)
     *  2、只要是在主队列中,添加进来的操作,都在主线程上(1)
     *  两个队列不能同时抢一个任务操作
     */
    -(void)opDemo1{
      NSOperationQueue *queue=[[NSOperationQueue alloc]init];
      NSBlockOperation *b=[NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"%@",[NSThread currentThread]);
      }];
      [queue addOperation:b];
      [[NSOperationQueue mainQueue]addOperation:b];
    }
    /**
     *  同上
     */
    -(void)opDemo2{
      NSInvocationOperation *i=[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(helloWorld) object:nil];
      NSOperationQueue *queue=[[NSOperationQueue alloc]init];
      [queue addOperation:i];
      [[NSOperationQueue mainQueue]addOperation:i];
    }
    -(void)helloWorld{
      NSLog(@"hello,world!");
    }
    /**
     *  依赖关系:(1)可以保证执行顺序,也使得开的子线程不会太多;(2)可以跨队列,而串行是不可以跨队列的,如最后更新UI则变成在主队列中。
     *  这是NSOperation(NSBlockOperation和NSInvocationOperation)和NSOperationQueue的优势
     */
    -(void)opDemo3{
      NSBlockOperation *op1=[NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"下载图片 %@",[NSThread currentThread]);
      }];
      NSBlockOperation *op2=[NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"修饰图片 %@",[NSThread currentThread]);
      }];
      NSBlockOperation *op3=[NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"保存图片 %@",[NSThread currentThread]);
      }];
      NSBlockOperation *op4=[NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"更新UI %@",[NSThread currentThread]);
      }];
      [op4 addDependency:op3];
      [op3 addDependency:op2];
      [op2 addDependency:op1];
      NSOperationQueue *queue=[[NSOperationQueue alloc]init];
      //设置同一时刻最大开启的线程数,这是NSOperationQueue特有的
      [queue setMaxConcurrentOperationCount:2];
      [queue addOperation:op1];
      [queue addOperation:op2];
      [queue addOperation:op3];
      [[NSOperationQueue mainQueue]addOperation:op4];
    }
    

    (3)单例的实现(手写单例要求)dispatch_once运用,即重写类的allocWithZone方法

    @implementation WPObject
    +(instancetype)allocWithZone:(struct _NSZone *)zone{
      static WPObject *insta;
      static dispatch_once_t onceToken;
      dispatch_once(&onceToken, ^{
        insta=[super allocWithZone:zone];
      });
      return insta;
    }
    @end
  • 相关阅读:
    50个jQuery 插件可将你的网站带到另外一个高度
    Web 开发中 20 个很有用的 CSS 库
    【算法】1、约瑟夫环
    智造微博
    银河系中央超大黑洞可能是个虫洞 其连接着两个不同的时空。
    创意文案:我害怕阅读的人
    解决Oracle ORA-00984: column not allowed here
    舌尖上的程序员
    技术贴 本地代码与svn关联教程 svn upgrade问题解决
    Aimp3的播放列表 按评分排序 落雨
  • 原文地址:https://www.cnblogs.com/conanwin/p/5549052.html
Copyright © 2020-2023  润新知