iOS GCD详解一

2020-03-19  本文已影响0人  KOLee

什么是GCD?

Grand Central Dispatch (GCD) 是异步执行任务之一,即开发者要做的只是定义想执行的任务追加到适当的Dispatch Queue 中。GCD存在于两种Dispatch Queue,一种是要等待上一个执行完,再执行下一个的Serial Dispatch Queue,这叫做串行队列;另一种,则是不需要上一个执行完,就能执行下一个的Concurrent Dispatch Queue,叫做并行队列。这两种,均遵循FIFO(先进先出)原则。

同步与异步

串行与并行针对的是队列,而同步与异步,针对的则是线程。最大的区别在于,同步线程要阻塞当前线程,必须要等待同步线程中的任务执行完,返回以后,才能继续执行下一任务,整个过程是不会创建新线程的;而异步线程则是不用等待,会在新开启的线程中执行任务(执行主队列的任务除外,主队列的任务在主线程中执行)。

GCD的API

一、 dispatch_queue_create


/// 第一个参数为 Serial Dispatch Queue 名称  第二个参数设为 NULL
dispatch_queue_t mySerialDispatchQueue = dispatch_queue_create("com.example.gcd.mySerialDispatchQueue ", NULL);
   ///同步线程
   dispatch_sync(mySerialDispatchQueue, ^{
           //  想执行的任务
   });
   ///异步线程
   dispatch_async(mySerialDispatchQueue, ^{
           //  想执行的任务
   });
    /// 第一个参数为 Concurrent Dispatch Queue 名称  第二个参数设为 NULL
    dispatch_queue_t myConcurrent lDispatchQueue = dispatch_queue_create("com.example.gcd.myConcurrent DispatchQueue ", DISPATCH_QUEUE_CONCURRENT);
    ///同步线程
    dispatch_sync(mySerialDispatchQueue, ^{
            //  想执行的任务
    });
    ///异步线程
    dispatch_async(mySerialDispatchQueue, ^{
            //  想执行的任务
    });

二、 Main Dispatch Queue/Global Dispatch Queue

  1. Main Dispatch Queue获取如下:
 dispatch_queue_t mainQueue = dispatch_get_main_queue();
    dispatch_async(mainQueue, ^{
         //  想执行的任务
    });

2.Global Dispatch Queue有4个优先级:

各种Dispatch Queue 获取如下:
   /// 高优先级
    dispatch_queue_t globalDisPathQueueHeigh = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
    
    /// 默认优先级
    dispatch_queue_t globalDisPathQueueDefault = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    /// 低优先级
    dispatch_queue_t globalDisPathQueueLow = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);

    /// 后台优先级
    dispatch_queue_t globalDisPathQueueBackground = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);

三、 dispatch_set_target_queue

  1. 变更执行优先级
      //优先级变更的串行队列,初始是默认优先级
    dispatch_queue_t serialQueue = dispatch_queue_create("com.gcd.serialQueue", NULL);
            
    //获取优先级为后台优先级的全局队列
    dispatch_queue_t globalDefaultQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
    //变更优先级
                                    
    dispatch_set_target_queue(serialQueue, globalDefaultQueue);

2.设置执行阶层

 //创建目标串行队列
 dispatch_queue_t targetSerialQueue = dispatch_queue_create("com.gcd.targetSerialQueue", DISPATCH_QUEUE_SERIAL);

 //设置执行阶层
 dispatch_set_target_queue(serialQueue1, targetSerialQueue);
 dispatch_set_target_queue(serialQueue2, targetSerialQueue);
 dispatch_set_target_queue(serialQueue3, targetSerialQueue);

   dispatch_async(serialQueue1, ^{
     NSLog(@"1 in");
     [NSThread sleepForTimeInterval:3.f];
     NSLog(@"1 out");
 });
 dispatch_async(serialQueue2, ^{
     NSLog(@"2 in");
     [NSThread sleepForTimeInterval:3.f];
     NSLog(@"2 out");
 });
 dispatch_async(serialQueue3, ^{
     NSLog(@"3 in");
     [NSThread sleepForTimeInterval:3.f];
     NSLog(@"3 out");
 });
打印结果:
2020-03-19 12:49:13.250818+0800 GCDDemo[1602:70311] 1 in
2020-03-19 12:49:16.251712+0800 GCDDemo[1602:70311] 1 out
2020-03-19 12:49:16.252179+0800 GCDDemo[1602:70311] 2 in
2020-03-19 12:49:19.255916+0800 GCDDemo[1602:70311] 2 out
2020-03-19 12:49:19.256236+0800 GCDDemo[1602:70311] 3 in
2020-03-19 12:49:22.261592+0800 GCDDemo[1602:70311] 3 out

四、 dispatch_after

 NSLog(@"第一步");
     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
         NSLog(@"我是延迟执行的函数 ---%@",[NSThread currentThread]);
     });
     
     NSLog(@"耗时任务开始");
     NSInteger count = 0;
     for (long long i = 0; i < 5000000000; i++)
     {
         count ++;
     }
     NSLog(@"耗时任务结束");
打印结果:
2020-03-19 13:06:13.527401+0800 GCDDemo[1656:78117] 第一步
2020-03-19 13:06:13.527552+0800 GCDDemo[1656:78117] 耗时任务开始
2020-03-19 13:06:25.103525+0800 GCDDemo[1656:78117] 耗时任务结束
2020-03-19 13:06:25.125003+0800 GCDDemo[1656:78117] 我是延迟执行的函数 ---<NSThread: 0x600003a9a0c0>{number = 1, name = main}

通过执行结果我们可以发现,dispatch_after函数block内的打印是在12秒以后才执行,并不是我们设置的5秒,这是因为此时dispatch_after函数的第二个参数传入的是主线程,延迟任务添加在了主线程中,而主线程中有一个耗时的打印任务,要等这个耗时任务执行完才执行dispatch_after的block。

下面我们将dispatch_after函数第二个参数改成另一个队列

  dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_CONCURRENT);
   NSLog(@"第一步");
   dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), queue, ^{
       NSLog(@"我是延迟执行的函数 ---%@",[NSThread currentThread]);
   });
   
   NSLog(@"耗时任务开始");
   NSInteger count = 0;
   for (long long i = 0; i < 5000000000; i++)
   {
       count ++;
   }
   NSLog(@"耗时任务结束");
打印结果:
2020-03-19 13:10:10.659080+0800 GCDDemo[1694:81120] 第一步
2020-03-19 13:10:10.659228+0800 GCDDemo[1694:81120] 耗时任务开始
2020-03-19 13:10:15.659324+0800 GCDDemo[1694:81249] 我是延迟执行的函数 ---<NSThread: 0x600001146f80>{number = 6, name = (null)}
2020-03-19 13:10:22.447207+0800 GCDDemo[1694:81120] 耗时任务结束

我们发现确实是按照我们设定的5秒执行的

五、 Dispatch Group

   /// 获取一个global线程
   dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
   /// 创建一个组线程
   dispatch_group_t group = dispatch_group_create();
   
   dispatch_group_async(group, queue, ^{
       NSLog(@"blk0");
   });
   dispatch_group_async(group, queue, ^{
         NSLog(@"blk1");
     });
   dispatch_group_async(group, queue, ^{
         NSLog(@"blk2");
     });
   
   dispatch_group_notify(group, dispatch_get_main_queue(), ^{
       NSLog(@"done");
   });
打印结果:
2020-03-19 17:38:03.313181+0800 GCDDemo[1974:110534] blk0
2020-03-19 17:38:03.313181+0800 GCDDemo[1974:110530] blk1
2020-03-19 17:38:03.313192+0800 GCDDemo[1974:110532] blk2
2020-03-19 17:38:03.328668+0800 GCDDemo[1974:110352] done

所以无论如何添加Dispatch Queue 到Dispatch Group,都可以监听这些处理的结束,其他的方法还有:

上一篇 下一篇

猜你喜欢

热点阅读