GCD

作者: tushizhan | 来源:发表于2016-12-26 15:25 被阅读0次

    锁对象:锁对象必须是全局的,还要继承于NSObject;
    互斥锁使用线程同步技术;
    任务 :决定的是执行的方式,在哪里执行,是在当前的线程执行,还是再开辟一条线程执行;
    队列: 决定的是任务的调度方式;决定的是任务怎么执行,是按照顺序还是不按照顺序

    GCD:grand central dispatch是苹果公司为多核并行运算提出的方案;自动利用更多的cpu内核,自动管理线程的生命周期
    核心:将任务添加到队列; 任务:执行什么操作,一般是block代码,队列:相当于容器,用来存放任务;
    步骤:创建队列,创建任务 (确定要做的事情),添加任务到队列;GCD会自动的将队列中的任务取出来,放到对应的线程中执行;
    队列的特点:先进先出(FIFO);
    NSThread的任务封装在”方法中”;GCD的任务封装在”BLOCK”中;

    BLOCK :属于C语言框架
    是一种数据类型数据类型 :void (^) ( )
    变量名 :void (^myBlock) ( )
    赋值 :void (^myBlock) () = ^{ };

    是一段代码块,被调用的时候才会执行 (类似于函数和方法);
    可以定义为临时变量
    可以定义函数
    可以定义成属性
    本质是函数指针;

    block内存arc环境下,定义的单纯的block存储在全局区; <NSGlobalBlock>
    访问外部变量,block储存在堆区;访问之前,变量在栈区; 0x7fff
    访问时,变量被block拷贝到堆区 0x7fe
    访问结束,变量的地址又回到栈区;

    修改外部变量:block内部不能修改外部变量,如果修改的话,将外部变量用__Block修饰;
    修改之前,变量地址在栈区,在block外面,用__block修饰了,地址不会变
    修改时,变量地址跑到了堆区;
    修改完成后,变量的地址回不到栈区了,留在了堆区;

    MAR下:定义的单纯的block存储在全局区; <NSGlobalBlock>
    访问外部变量:访问之前,栈区;
    访问时,依然在栈区
    访问之后,栈区,但是地址变了,内存空间没有变;

    修改外部变量:修改之前,栈区
    修改,栈区
    修改之后,栈区,而且地址没有变;

    block作为属性,MRC要用copy修饰 (ARC下strong也可以),因为要全局共享,所以放在了堆区.

    GCD- (void)GCDDemo1{ //1.创建队列 //数据类型 变量名 dispatch_queue_t queue = dispatch_get_global_queue(0, 0); //2.创建任务 : void (^myTask)() = ^{ //代码块中是GCD要执行的任务 NSLog(@"%@",[NSThread currentThread]); }; //3.将任务添加到队列中 dispatch_async(queue, myTask);}
    //简写demo1- (void)GCDDemo2{ dispatch_async(dispatch_get_global_queue(0, 0), ^{ NSLog(@"%@",[NSThread currentThread]); });}

    pragma mark - GCD实现线程间的通信- (void)GCDDemo3{ dispatch_async(dispatch_get_global_queue(0, 0), ^{ NSLog(@"加载在下载... %@",[NSThread currentThread]); // 下载结束了,回到主线程刷新UI dispatch_async(dispatch_get_main_queue(), ^{ NSLog(@"刷新UI... %@",[NSThread currentThread]); }); });}

    串行队列:里面的任务按照顺序依次调度执行,前面一个任务不执行完,后面的任务不会被调度. Serial 同时只能调度一个任务执行;队列的创建:dispatch_queue_t queue = dispatch_queue_create("TT", DISPATCH_QUEUE_SERIAL);

    串行➕异步:会开一条心线程,因为是异步,而且mm不会最后打印,循环是有顺序的;- (void)GCDDemo1{ //创建队列 dispatch_queue_t queue = dispatch_queue_create("tt", DISPATCH_QUEUE_SERIAL); for (NSInteger i = 0; i < 10; i++) { //创建任务 void(^task)() = ^{ NSLog(@"%zd %@",i ,[NSThreadcurrentThread]); }; //添加到队列异步 dispatch_async(queue, task); } NSLog(@"mm");}

    串行➕同步 :不会开新线程,会在当前的线程执行,mm会最后打印,循环是有顺序的- (void)GCDDemo1{ //创建队列 dispatch_queue_t queue = dispatch_queue_create("tt", DISPATCH_QUEUE_SERIAL); for (NSInteger i = 0; i < 10; i++) { //创建任务 void(^task)() = ^{ NSLog(@"%zd %@",i ,[NSThreadcurrentThread]); }; //添加到队列同步 dispatch_sync(queue, task); } NSLog(@"mm");}

    并发队列:可以同时调度多个任务同时执行; Concurrent 自动开启多个线程同时执行多个任务
    主队列:专门在主线程上调度任务,不会开启新线程,先进先出的方式,只有主线程空闲时才会调度队列中的任务在主任务执行,如果当前主线程有任务在执行,无论主队列被添加了什么任务,都不会被调度.dispatch_queue_t queue = dispatch_get_main_queue ();

    全局队列:效果等同于并发队列;

    任务:dispatch_sync (dispatch_queue_t queue ,dispatch_block_t block); 同步方式执行任务,只在当前的线程中依次执行任务;
    dispatch_async (dispatch_queue_t queue ,dispatch_block_t block); 异步方式执行任务,新开线程,在新线程中执行任务;

    dispatch_after (when ,queue ,block);真的一个异步函数;

    同步任务由于是从上到下执行,可以知道具体哪个任务执行完了,但是异步任务顺序不一样,无法知道具体哪个任务完成了;调度组用来监听一组异步任务的状况;dispatch_group_async ();

    单例特点:有一个方便外界调用的类方法,用来实例化单例对象;
    保证这个类在程序运行的过程中,在内存中有且只有一个实例化对象
    保存在内存的静态区(保证单例的生命周期和程序一样长)

    缺点:单例保存在静态区,只有在APP死亡时才会结束;
    static AudioTool *instance;+ (instancetype)sharedAudioTool{ static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ instance = [[AudioTool alloc] init]; }); return instance;}//由于viewController.m中alloc和shared调用的顺序不一样,所以后面的实现方法里面都重写一下dispatch_once,但是copy是对象copy,所以不用重写+ (instancetype)allocWithZone:(struct _NSZone *)zone{ static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ instance = [super allocWithZone:zone]; }); return instance;}- (id)copyWithZone:(NSZone *)zone{ return instance;}

    • 遍历

      • 下标遍历
      for i in 0..<array.count {
       print(array[i]) //输出:小明            
                       //     中花  
                       //     大杨
      }   
      
      • 直接内容遍历
      for s in array {
          print(s) //输出:小明
                   //     中花
                   //     大杨
       }
      
      • enum block遍历下标和内容
       for e in array.enumerated() {
          print("\(e.offset) \(e.element)") //输出:0 小明
                                            //     1 中花
                                            //     2 大杨
       }
      
      • 遍历下标和内容方式二
      for(n, s) in array.enumerated() {
              print("\(n) \(s)")  //输出:0 小明
                                  //     1 中花
                               //     2 大杨
      }
      
      • 反序
       for s in array.reversed() {
              print(s) //输出:大杨
                       //     中花
                       //     小明
      }
      
      • 反序索引和内容
      //错的
      for (n, s) in array.reversed().enumerated() {
          print("\(n) \(s)")  //输出:0 大杨
                              //     1 中花
                              //     2 小明
      }
      //对的
      for (n, s) in array.enumerated().reversed() {
          print("\(n) \(s)") //输出:2 大杨
                             //    1 中花
                             //    0 小明
      }
      
    - **增**

    相关文章

      网友评论

          本文标题:GCD

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