美文网首页
多线程:GCD

多线程:GCD

作者: 小小鸟他大爷 | 来源:发表于2020-12-26 15:25 被阅读0次

    多线程:GCD

    The main queue(主线程串行队列): 与主线程功能相同,提交至Main queue的任务会在主线程中执行,

    1.  Main queue 可以通过dispatch_get_main_queue()来获取。

    2.  Global queue(全局并发队列): 全局并发队列由整个进程共享,有高、中(默认)、低、后台四个优先级别。

    Global queue 可以通过调用dispatch_get_global_queue函数来获取(可以设置优先级)

    3.  Custom queue (自定义队列): 可以为串行,也可以为并发。

    Custom queue 可以通过dispatch_queue_create()来获取;

    4.  Group queue (队列组):将多线程进行分组,最大的好处是可获知所有线程的完成情况。

    Group queue 可以通过调用dispatch_group_create()来获取,通过dispatch_group_notify,可以直接监听组里所有线程完成情况。

    Global queue

    获取全局并发队列

    //程序默认的队列级别,一般不要修改,DISPATCH_QUEUE_PRIORITY_DEFAULT == 0

    dispatch_queue_t globalQueue1 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    //HIGH

    dispatch_queue_t globalQueue2 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);

    //LOW

    dispatch_queue_t globalQueue3 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);

    //BACKGROUND

    dispatch_queue_t globalQueue4 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);

    全局并发队列由系统默认生成的,所以无法调用dispatch_resume()和dispatch_suspend()来控制执行继续或中断。

    Custom queue 

    1.自定义串行队列会发生死锁

    注意不要嵌套使用同步执行的串行队列任务

    dispatch_queue_t serialQueue = dispatch_queue_create("com.dullgrass.serialQueue", DISPATCH_QUEUE_SERIAL);

    dispatch_async(serialQueue, ^{

      NSLog(@"会执行的代码");

      dispatch_sync(serialQueue, ^{

          NSLog(@"代码不执行");

      });

    });

    2.自定义并发队列

    dispatch_queue_t conCurrentQueue = dispatch_queue_create("com.dullgrass.conCurrentQueue", DISPATCH_QUEUE_CONCURRENT);

    NSLog(@"current task");

    dispatch_sync(conCurrentQueue, ^{

         NSLog(@"先加入队列");

    });

    dispatch_sync(conCurrentQueue, ^{

         NSLog(@"次加入队列");

    });

    NSLog(@"next task");

    Group queue

    1.使用场景: 同时下载多个图片,所有图片下载完成之后去更新UI(需要回到主线程)或者去处理其他任务(可以是其他线程队列)。

    原理:使用函数dispatch_group_create创建dispatch group,然后使用函数dispatch_group_async来将要执行的block任务提交到一个dispatch queue。同时将他们添加到一个组,等要执行的block任务全部执行完成之后,使用dispatch_group_notify函数接收完成时的消息。

    dispatch_queue_t conCurrentGlobalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    dispatch_queue_t mainQueue = dispatch_get_main_queue();

    dispatch_group_t groupQueue = dispatch_group_create();

    NSLog(@"current task");

    dispatch_group_async(groupQueue, conCurrentGlobalQueue, ^{

          NSLog(@"并行任务1");

    });

    dispatch_group_async(groupQueue, conCurrentGlobalQueue, ^{

          NSLog(@"并行任务2");

    });

    dispatch_group_notify(groupQueue, mainQueue, ^{

          NSLog(@"groupQueue中的任务 都执行完成,回到主线程更新UI");

    });

    NSLog(@"next task");

    2015-11-19 13:47:55.117 Whisper[1645:97116] current task

    2015-11-19 13:47:55.117 Whisper[1645:97116] next task

    2015-11-19 13:47:55.119 Whisper[1645:97178] 并行任务1

    2015-11-19 13:47:55.119 Whisper[1645:97227] 并行任务2

    2015-11-19 13:47:55.171 Whisper[1645:97116] groupQueue中的任务 都执行完成,回到主线程更新UI

    1.dispatch_after延时添加到队列

    dispatch_time_t delayTime3 = dispatch_time(DISPATCH_TIME_NOW, 3*NSEC_PER_SEC);

    dispatch_time_t delayTime2 = dispatch_time(DISPATCH_TIME_NOW, 2*NSEC_PER_SEC);

    dispatch_queue_t mainQueue = dispatch_get_main_queue();

    NSLog(@"current task");

    dispatch_after(delayTime3, mainQueue, ^{

          NSLog(@"3秒之后添加到队列");

    });

    dispatch_after(delayTime2, mainQueue, ^{

           NSLog(@"2秒之后添加到队列");

    });

    NSLog(@"next task");

    2015-11-19 15:50:19.369 Whisper[2725:172593] current task

    2015-11-19 15:50:19.370 Whisper[2725:172593] next task

    2015-11-19 15:50:21.369 Whisper[2725:172593] 2秒之后添加到队列

    2015-11-19 15:50:22.654 Whisper[2725:172593] 3秒之后添加到队列

    dispatch_after只是延时提交block,并不是延时后立即执行,并不能做到精确控制,需要精确控制的朋友慎用哦

    dispatch_apply在给定的队列上多次执行某一任务,在主线程直接调用会阻塞主线程去执行block中的任务。

    dispatch_apply函数的功能:把一项任务提交到队列中多次执行,队列可以是串行也可以是并行,dispatch_apply不会立刻返回,在执行完block中的任务后才会返回,是同步执行的函数。

    dispatch_apply正确使用方法:为了不阻塞主线程,一般把dispatch_apply放在异步队列中调用,然后执行完成后通知主线程

    dispatch_queue_t globalQueue = dispatch_get_global_queue(0, 0);

    NSLog(@"current task");

    dispatch_async(globalQueue, ^{

       dispatch_queue_t applyQueue= dispatch_get_global_queue(0, 0);

       //第一个参数,3--block执行的次数

       //第二个参数,applyQueue--block任务提交到的队列

       //第三个参数,block--需要重复执行的任务

       dispatch_apply(3, applyQueue, ^(size_t index) {

              NSLog(@"current index %@",@(index));

              sleep(1);

       });

       NSLog(@"dispatch_apply 执行完成");

       dispatch_queue_t mainQueue= dispatch_get_main_queue();

       dispatch_async(mainQueue, ^{

              NSLog(@"回到主线程更新UI");

      });

    });

    NSLog(@"next task");

    2015-11-19 16:24:45.015 Whisper[4034:202269] current task

    2015-11-19 16:24:45.016 Whisper[4034:202269] next task

    2015-11-19 16:24:45.016 Whisper[4034:202347] current index 0

    2015-11-19 16:24:45.016 Whisper[4034:202344] current index 1

    2015-11-19 16:24:45.016 Whisper[4034:202345] current index 2

    2015-11-19 16:24:46.021 Whisper[4034:202347] dispatch_apply 执行完成

    2015-11-19 16:24:46.021 Whisper[4034:202269] 回到主线程更新UI

    嵌套使用dispatch_apply会导致死锁

    3.dispatch_once保证在app运行期间,block中的代码只执行一次

    //GCD实现单例功能

    + (ShareManager *)shareManager

    {

      static dispatch_once_t onceToken;

      dispatch_once(&onceToken, ^{

          sharedManager= [[self alloc] init];

      });

      return sharedManager;

     }

    //在ARC下,非GCD,实现单例功能

    + (ShareManager *)sharedManager

    {

      @synchronized(self) {

          if (!sharedManager) {

              sharedManager= [[self alloc] init];

          }

      }

      return sharedManager;

     }

    4.dispatch_barrier_async 栅栏的作用

    功能:是在并行队列中,等待在dispatch_barrier_async之前加入的队列全部执行完成之后(这些任务是并发执行的)再执行dispatch_barrier_async中的任务,dispatch_barrier_async中的任务执行完成之后,再去执行在dispatch_barrier_async之后加入到队列中的任务(这些任务是并发执行的)

    dispatch_queue_t conCurrentQueue = dispatch_queue_create("com.dullgrass.conCurrentQueue", DISPATCH_QUEUE_CONCURRENT);

    dispatch_async(conCurrentQueue, ^{

          NSLog(@"dispatch 1");

    });

    dispatch_async(conCurrentQueue, ^{

           NSLog(@"dispatch 2");

    });

    dispatch_barrier_async(conCurrentQueue, ^{

           NSLog(@"dispatch barrier");

    });

    dispatch_async(conCurrentQueue, ^{

           NSLog(@"dispatch 3");

    });

    dispatch_async(conCurrentQueue, ^{

           NSLog(@"dispatch 4");

    });

    2015-11-19 18:12:34.125 Whisper[22633:297257] dispatch 1

    2015-11-19 18:12:34.125 Whisper[22633:297258] dispatch 2

    2015-11-19 18:12:34.126 Whisper[22633:297258] dispatch barrier

    2015-11-19 18:12:34.127 Whisper[22633:297258] dispatch 3

    2015-11-19 18:12:34.127 Whisper[22633:297257] dispatch 4

    相关文章

      网友评论

          本文标题:多线程:GCD

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