iOS多线程(3)-GCD

  • 简介:

    为什么要用 GCD 呢?因为 GCD 有很多好处啊,具体如下:
    GCD 可用于多核的并行运算
    GCD 会自动利用更多的 CPU 内核(比如双核、四核)
    GCD 会自动管理线程的生命周期(创建线程、调度任务、销毁线程)
    程序员只需要告诉 GCD 想要执行什么任务,不需要编写任何线程管理代码
    既然 GCD 有这么多的好处,那么下面我们就来系统的学习一下 GCD 的使用方法。

目录:

  • 队列创建

  • 同步异步

  • 线程间通讯

  • 延迟执行(dispatch_after)

  • 定时器(dispatch_timer)

  • 一次执行(dispatch_once)

  • 迭代(dispatch_apply)

  • 队列组(dispatch_group_notify)

  • 等待(dispatch_group_wait)

  • 信号(dispatch_semaphore_t)

  • 并发控制通过信号实现

  • 队列创建:
    //串行队列
    dispatch_queue_t queue = dispatch_queue_create("com.gcd.peace", DISPATCH_QUEUE_SERIAL);
    //并行队列
    dispatch_queue_t queue = dispatch_queue_create("com.gcd.peace", DISPATCH_QUEUE_CONCURRENT);
    //全局并行队列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    //主线程队列
    dispatch_queue_t queue = dispatch_get_main_queue();
    
  • 同步异步:
    - (void)asyncAction {
      dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
      dispatch_async(queue, ^{
          NSLog(@"async---%@",[NSThread currentThread]);
      });
    }
    
    - (void)syncAction {
      dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
      dispatch_sync(queue, ^{
          NSLog(@"sync---%@",[NSThread currentThread]);
      });
    }
    
    输出:
    ---{number = 5, name = (null)}
    ---{number = 1, name = main}
    
  • 线程间通讯:
    - (void)asyncToSyncAction {
      dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
          NSLog(@"---%@",[NSThread currentThread]);
          
          // 回到主线程
          dispatch_async(dispatch_get_main_queue(), ^{
              NSLog(@"---%@",[NSThread currentThread]);
          });
      });
    }
    
    输出:
    ---{number = 5, name = (null)}
    ---{number = 1, name = main}
    
  • 栅栏(dispatch_barrier_async):
    - (void)barrierAction {
        dispatch_queue_t queue = dispatch_queue_create("com.gcd.peace", DISPATCH_QUEUE_CONCURRENT);
      
        for (int i = 0; i < 10; i ++) {
            dispatch_async(queue, ^{
                [NSThread sleepForTimeInterval:2];
                NSLog(@"1---%@",[NSThread currentThread]);
            });
        }
      
        //barrier
        dispatch_barrier_async(queue, ^{
            [NSThread sleepForTimeInterval:2];
            NSLog(@"[Barrier: ---%@",[NSThread currentThread]);
        });
    
        for (int i = 0; i < 10; i ++) {
            dispatch_async(queue, ^{
                [NSThread sleepForTimeInterval:2];
                NSLog(@"3---%@",[NSThread currentThread]);
            });
        }
    }
    
    输出:
    2018-03-20 17:57:39.417137+0800 GCD[55856:2568834] 1---{number = 6, name = (null)}
    2018-03-20 17:57:39.417137+0800 GCD[55856:2568833] 1---{number = 3, name = (null)}
    2018-03-20 17:57:39.417138+0800 GCD[55856:2568832] 1---{number = 4, name = (null)}
    2018-03-20 17:57:39.417148+0800 GCD[55856:2568835] 1---{number = 5, name = (null)}
    2018-03-20 17:57:39.417197+0800 GCD[55856:2568853] 1---{number = 7, name = (null)}
    2018-03-20 17:57:39.417247+0800 GCD[55856:2568855] 1---{number = 8, name = (null)}
    2018-03-20 17:57:39.417308+0800 GCD[55856:2568856] 1---{number = 10, name = (null)}
    2018-03-20 17:57:39.417329+0800 GCD[55856:2568854] 1---{number = 9, name = (null)}
    2018-03-20 17:57:39.417344+0800 GCD[55856:2568857] 1---{number = 11, name = (null)}
    2018-03-20 17:57:39.417361+0800 GCD[55856:2568858] 1---{number = 12, name = (null)}
    2018-03-20 17:57:41.420468+0800 GCD[55856:2568858] [Barrier: ---{number = 12, name = (null)}
    2018-03-20 17:57:43.423862+0800 GCD[55856:2568858] 3---{number = 12, name = (null)}
    2018-03-20 17:57:43.423827+0800 GCD[55856:2568855] 3---{number = 8, name = (null)}
    2018-03-20 17:57:43.423826+0800 GCD[55856:2568854] 3---{number = 9, name = (null)}
    2018-03-20 17:57:43.423827+0800 GCD[55856:2568857] 3---{number = 11, name = (null)}
    2018-03-20 17:57:43.423855+0800 GCD[55856:2568853] 3---{number = 7, name = (null)}
    2018-03-20 17:57:43.423823+0800 GCD[55856:2568856] 3---{number = 10, name = (null)}
    2018-03-20 17:57:43.423949+0800 GCD[55856:2568834] 3---{number = 6, name = (null)}
    2018-03-20 17:57:43.423952+0800 GCD[55856:2568833] 3---{number = 3, name = (null)}
    2018-03-20 17:57:43.423960+0800 GCD[55856:2568835] 3---{number = 5, name = (null)}
    2018-03-20 17:57:43.423964+0800 GCD[55856:2568832] 3---{number = 4, name = (null)}
    
  • 延迟执行(dispatch_after):
    - (void)afterAction {
      NSLog(@"[After]: begin currentThread---%@",[NSThread currentThread]);
      
      dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
          NSLog(@"[After]: main ---%@",[NSThread currentThread]);
      });
      
      dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
          NSLog(@"[After]: global ---%@",[NSThread currentThread]);
      });
    }
    
    输出:
    2018-03-20 18:01:33.749444+0800 GCD[55856:2568766] [After]: begin currentThread---{number = 1, name = main}
    2018-03-20 18:01:35.928257+0800 GCD[55856:2568766] [After]: main ---{number = 1, name = main}
    2018-03-20 18:01:35.928274+0800 GCD[55856:2571380] [After]: global ---{number = 13, name = (null)}
    
  • 定时器(dispatch_timer):
    @property(nonatomic,strong) dispatch_source_t tTimer;
    
    - (void)timerAction {
     NSLog(@"[Timer]: begin currentThread---%@",[NSThread currentThread]);
     
     if (!self.tTimer) {
         self.tTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
         NSLog(@"self.tTimer = %@",self.tTimer);
         dispatch_source_set_timer(self.tTimer,
                                   dispatch_walltime(NULL, 0 * NSEC_PER_SEC),
                                   0.32 * NSEC_PER_SEC,
                                   0);
         dispatch_source_set_event_handler(self.tTimer, ^{
             NSLog(@"1111");
         });
     
         dispatch_resume(self.tTimer);
     }
     else {
         dispatch_source_cancel(self.tTimer);
         self.tTimer = nil;
     }
     //        dispatch_suspend(self.tTimer);
     //        dispatch_source_cancel(self.tTimer);
     //        self.tTimer = nil; Crash
     
     //        dispatch_suspend(self.tTimer);
     //        self.tTimer = nil; Crash
    }
    
  • 一次执行(dispatch_once):
    - (void)onceAction {
      __block int index = 0;
      for (int i = 0; i < 10; i ++) {
          static dispatch_once_t onceToken;
          dispatch_once(&onceToken, ^{
              index ++;
              NSLog(@"[Once]:-------index = %d",index);
          });
      }
    }
    
    输出:
    2018-03-20 18:03:17.189632+0800 GCD[55856:2568766] [Once]:-------index = 1
    
  • 迭代(dispatch_apply):
    - (void)applyAction {
      //并行迭代
      dispatch_queue_t queue = dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
      //串行队列迭代与for循环效果一样
      //queue = dispatch_queue_t queue = dispatch_queue_create("com.gcd.peace", DISPATCH_QUEUE_SERIAL);
      
      NSLog(@"apply---begin");
      dispatch_apply(6, queue, ^(size_t index) {
          NSLog(@"%zd---%@",index, [NSThread currentThread]);
          [NSThread sleepForTimeInterval:2];
      });
      NSLog(@"apply---end");
    }
    
    并行队列输出:
    2018-03-20 18:05:42.458703+0800 GCD[56041:2574450] apply---begin
    2018-03-20 18:05:42.459384+0800 GCD[56041:2574450] 0---{number = 1, name = main}
    2018-03-20 18:05:42.459417+0800 GCD[56041:2574512] 1---{number = 3, name = (null)}
    2018-03-20 18:05:42.459504+0800 GCD[56041:2574499] 4---{number = 7, name = (null)}
    2018-03-20 18:05:42.459504+0800 GCD[56041:2574502] 3---{number = 4, name = (null)}
    2018-03-20 18:05:42.459506+0800 GCD[56041:2574500] 5---{number = 6, name = (null)}
    2018-03-20 18:05:42.459521+0800 GCD[56041:2574501] 2---{number = 5, name = (null)}
    2018-03-20 18:05:44.463743+0800 GCD[56041:2574450] apply---end
    
    串行队列输出:
    2018-03-20 18:07:33.988048+0800 GCD[56083:2576141] apply---begin
    2018-03-20 18:07:33.988516+0800 GCD[56083:2576141] 0---{number = 1, name = main}
    2018-03-20 18:07:35.989109+0800 GCD[56083:2576141] 1---{number = 1, name = main}
    2018-03-20 18:07:37.990556+0800 GCD[56083:2576141] 2---{number = 1, name = main}
    2018-03-20 18:07:39.992050+0800 GCD[56083:2576141] 3---{number = 1, name = main}
    2018-03-20 18:07:41.993583+0800 GCD[56083:2576141] 4---{number = 1, name = main}
    2018-03-20 18:07:43.995163+0800 GCD[56083:2576141] 5---{number = 1, name = main}
    2018-03-20 18:07:45.995811+0800 GCD[56083:2576141] apply---end
    
  • 队列组(dispatch_group_notify):
    - (void)groupNotifyAction {
      NSLog(@"group---begin");
      
      dispatch_group_t group = dispatch_group_create();
      dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
      
      dispatch_group_async(group, queue, ^{
          [NSThread sleepForTimeInterval:2];
          NSLog(@"1---%@",[NSThread currentThread]);
      });
      
      dispatch_group_async(group, queue, ^{
          [NSThread sleepForTimeInterval:2];
          NSLog(@"2---%@",[NSThread currentThread]);
      });
      
      dispatch_group_notify(group, [self mainQueue], ^{
          [NSThread sleepForTimeInterval:2];
          NSLog(@"3---%@",[NSThread currentThread]);
          NSLog(@"group notify");
      });
    }
    
    输出:
    2018-03-20 18:09:47.306064+0800 GCD[56083:2576141] group---begin
    2018-03-20 18:09:49.307609+0800 GCD[56083:2576199] 2---{number = 4, name = (null)}
    2018-03-20 18:09:49.307608+0800 GCD[56083:2577770] 1---{number = 3, name = (null)}
    2018-03-20 18:09:51.309380+0800 GCD[56083:2576141] 3---{number = 1, name = main}
    2018-03-20 18:09:51.309744+0800 GCD[56083:2576141] group notify
    
    - (void)groupNotify1Action {
      NSLog(@"group---begin");
      
      dispatch_group_t group = dispatch_group_create();
      dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
      
      dispatch_group_enter(group);
      dispatch_async(queue, ^{
          [NSThread sleepForTimeInterval:2];
          NSLog(@"1---%@",[NSThread currentThread]);
          dispatch_group_leave(group);
      });
      
      dispatch_group_enter(group);
      dispatch_async(queue, ^{
          [NSThread sleepForTimeInterval:5];
          NSLog(@"2---%@",[NSThread currentThread]);
          dispatch_group_leave(group);
      });
      
      dispatch_group_notify(group, [self mainQueue], ^{
          NSLog(@"group notify : %@",[NSThread currentThread]);
      });
    }
    
    输出:
    2018-03-20 18:09:53.329762+0800 GCD[56083:2576141] group---begin
    2018-03-20 18:09:55.332737+0800 GCD[56083:2576199] 1---{number = 4, name = (null)}
    2018-03-20 18:09:58.331259+0800 GCD[56083:2577770] 2---{number = 3, name = (null)}
    2018-03-20 18:09:58.331676+0800 GCD[56083:2576141] group notify : {number = 1, name = main}
    
  • 等待(dispatch_group_wait):
    - (void)groupWaitAction {
      NSLog(@"group---begin");
      
      dispatch_group_t group =  dispatch_group_create();
      dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
      
      dispatch_group_async(group, queue, ^{
          [NSThread sleepForTimeInterval:2];
          NSLog(@"1---%@",[NSThread currentThread]);
      });
      
      dispatch_group_async(group, queue, ^{
          [NSThread sleepForTimeInterval:5];
          NSLog(@"2---%@",[NSThread currentThread]);
      });
      
      dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
      
      NSLog(@"group---end");
    }
    
    输出:
    2018-03-20 18:12:57.523759+0800 GCD[56083:2576141] group---begin
    2018-03-20 18:12:59.527048+0800 GCD[56083:2579780] 1---{number = 5, name = (null)}
    2018-03-20 18:13:02.524335+0800 GCD[56083:2577781] 2---{number = 6, name = (null)}
    2018-03-20 18:13:02.524954+0800 GCD[56083:2576141] group---end
    
  • 信号(dispatch_semaphore_t):
    //通过信号实现同步功能
    - (void)semaphoreAction {
      NSLog(@"semaphore---begin");
      
      dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
      dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
      
      dispatch_async(queue, ^{
          [NSThread sleepForTimeInterval:2];
          NSLog(@"semaphore --- %@",[NSThread currentThread]);
          
          dispatch_semaphore_signal(semaphore);
      });
      
      dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);//信号量=0则阻挡,>0则通过
      NSLog(@"semaphore---end");
    }
    
    输出:
    2018-03-20 18:14:28.265856+0800 GCD[56083:2576141] semaphore---begin
    2018-03-20 18:14:30.271145+0800 GCD[56083:2580996] semaphore --- {number = 8, name = (null)}
    2018-03-20 18:14:30.271384+0800 GCD[56083:2576141] semaphore---end
    
    //通过信号实现锁
    - (void)semaphore1Action {
      dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
      dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
      
      for (int i = 0; i < 100; i++) {
          dispatch_async(queue, ^{
              // 相当于加锁
              dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
              NSLog(@"i = %zd semaphore = %@", i, semaphore);
              // 相当于解锁
              dispatch_semaphore_signal(semaphore);
          });
      }
    }
    
    输出:
    2018-03-20 18:16:21.561341+0800 GCD[56217:2582806] i = 0 semaphore = 
    2018-03-20 18:16:21.561717+0800 GCD[56217:2582805] i = 1 semaphore = 
    2018-03-20 18:16:21.561999+0800 GCD[56217:2582803] i = 2 semaphore = 
    2018-03-20 18:16:21.562277+0800 GCD[56217:2582804] i = 3 semaphore = 
    2018-03-20 18:16:21.562508+0800 GCD[56217:2582812] i = 4 semaphore = 
    2018-03-20 18:16:21.562745+0800 GCD[56217:2582823] i = 5 semaphore = 
    2018-03-20 18:16:21.562979+0800 GCD[56217:2582824] i = 6 semaphore = 
    2018-03-20 18:16:21.563213+0800 GCD[56217:2582825] i = 7 semaphore = 
    2018-03-20 18:16:21.563442+0800 GCD[56217:2582826] i = 8 semaphore = 
    2018-03-20 18:16:21.563671+0800 GCD[56217:2582827] i = 9 semaphore = 
    
  • 并发控制通过信号实现:
    void dispatch_async_limit(dispatch_queue_t queue,NSUInteger limitSemaphoreCount, dispatch_block_t block) {
      //控制并发数的信号量
      static dispatch_semaphore_t limitSemaphore;
      
      //专门控制并发等待的线程
      static dispatch_queue_t receiverQueue;
      
      //使用 dispatch_once而非 lazy 模式,防止可能的多线程抢占问题
      static dispatch_once_t onceToken;
      dispatch_once(&onceToken, ^{
          limitSemaphore = dispatch_semaphore_create(limitSemaphoreCount);
          receiverQueue = dispatch_queue_create("receiver", DISPATCH_QUEUE_SERIAL);
      });
      
      // 如不加 receiverQueue 放在主线程会阻塞主线程
      dispatch_async(receiverQueue, ^{
          //可用信号量后才能继续,否则等待
          dispatch_semaphore_wait(limitSemaphore, DISPATCH_TIME_FOREVER);
          dispatch_async(queue, ^{
              !block ? : block();
              //在该工作线程执行完成后释放信号量
              long semaphore = dispatch_semaphore_signal(limitSemaphore);
              if (semaphore > 0) {
                  NSLog(@"\n");
              }
          });
      });
    }
    
    - (void)limitAction {
      for (int i = 0; i < 10; i++) {
          dispatch_async_limit([self serialQueue],3, ^{
              sleep(2);
              NSLog(@"------i = %d",i);
          });
      }
    }
    
    输出:
    2018-03-20 17:33:45.367914+0800 GCD[55534:2553299] ------i = 1
    2018-03-20 17:33:45.367914+0800 GCD[55534:2553303] ------i = 0
    2018-03-20 17:33:45.367916+0800 GCD[55534:2553300] ------i = 2
    2018-03-20 17:33:45.368276+0800 GCD[55534:2553303] 
    2018-03-20 17:33:47.373465+0800 GCD[55534:2553300] ------i = 3
    2018-03-20 17:33:47.373482+0800 GCD[55534:2553299] ------i = 4
    2018-03-20 17:33:47.373496+0800 GCD[55534:2553302] ------i = 5
    2018-03-20 17:33:47.373856+0800 GCD[55534:2553300] 
    2018-03-20 17:33:49.379032+0800 GCD[55534:2553302] ------i = 6
    2018-03-20 17:33:49.379048+0800 GCD[55534:2553299] ------i = 7
    2018-03-20 17:33:49.379048+0800 GCD[55534:2553303] ------i = 8
    2018-03-20 17:33:49.379452+0800 GCD[55534:2553299] 
    2018-03-20 17:33:51.383480+0800 GCD[55534:2553301] ------i = 9
    
  • 源码:

    代码在这里

你可能感兴趣的:(iOS多线程(3)-GCD)