美文网首页
iOS多线程(3)-GCD

iOS多线程(3)-GCD

作者: WorldPeace_hp | 来源:发表于2018-03-20 18:21 被阅读0次
    • 简介:

      为什么要用 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]);
        });
      }
      
      输出:
      ---<NSThread: 0x60c00026bd40>{number = 5, name = (null)}
      ---<NSThread: 0x60000007f300>{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]);
            });
        });
      }
      
      输出:
      ---<NSThread: 0x60c00026bd40>{number = 5, name = (null)}
      ---<NSThread: 0x60000007f300>{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---<NSThread: 0x604000074780>{number = 6, name = (null)}
      2018-03-20 17:57:39.417137+0800 GCD[55856:2568833] 1---<NSThread:   0x6000002701c0>{number = 3, name = (null)}
      2018-03-20 17:57:39.417138+0800 GCD[55856:2568832] 1---<NSThread: 0x60c00007e7c0>{number = 4, name = (null)}
      2018-03-20 17:57:39.417148+0800 GCD[55856:2568835] 1---<NSThread: 0x60800007d7c0>{number = 5, name = (null)}
      2018-03-20 17:57:39.417197+0800 GCD[55856:2568853] 1---<NSThread: 0x600000270080>{number = 7, name = (null)}
      2018-03-20 17:57:39.417247+0800 GCD[55856:2568855] 1---<NSThread: 0x6040000754c0>{number = 8, name = (null)}
      2018-03-20 17:57:39.417308+0800 GCD[55856:2568856] 1---<NSThread: 0x60000026fac0>{number = 10, name = (null)}
      2018-03-20 17:57:39.417329+0800 GCD[55856:2568854] 1---<NSThread: 0x604000074a80>{number = 9, name = (null)}
      2018-03-20 17:57:39.417344+0800 GCD[55856:2568857] 1---<NSThread: 0x604000074380>{number = 11, name = (null)}
      2018-03-20 17:57:39.417361+0800 GCD[55856:2568858] 1---<NSThread: 0x60c00007e800>{number = 12, name = (null)}
      2018-03-20 17:57:41.420468+0800 GCD[55856:2568858] [Barrier: ---<NSThread: 0x60c00007e800>{number = 12, name = (null)}
      2018-03-20 17:57:43.423862+0800 GCD[55856:2568858] 3---<NSThread: 0x60c00007e800>{number = 12, name = (null)}
      2018-03-20 17:57:43.423827+0800 GCD[55856:2568855] 3---<NSThread: 0x6040000754c0>{number = 8, name = (null)}
      2018-03-20 17:57:43.423826+0800 GCD[55856:2568854] 3---<NSThread: 0x604000074a80>{number = 9, name = (null)}
      2018-03-20 17:57:43.423827+0800 GCD[55856:2568857] 3---<NSThread: 0x604000074380>{number = 11, name = (null)}
      2018-03-20 17:57:43.423855+0800 GCD[55856:2568853] 3---<NSThread: 0x600000270080>{number = 7, name = (null)}
      2018-03-20 17:57:43.423823+0800 GCD[55856:2568856] 3---<NSThread: 0x60000026fac0>{number = 10, name = (null)}
      2018-03-20 17:57:43.423949+0800 GCD[55856:2568834] 3---<NSThread: 0x604000074780>{number = 6, name = (null)}
      2018-03-20 17:57:43.423952+0800 GCD[55856:2568833] 3---<NSThread: 0x6000002701c0>{number = 3, name = (null)}
      2018-03-20 17:57:43.423960+0800 GCD[55856:2568835] 3---<NSThread: 0x60800007d7c0>{number = 5, name = (null)}
      2018-03-20 17:57:43.423964+0800 GCD[55856:2568832] 3---<NSThread: 0x60c00007e7c0>{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---<NSThread: 0x60000006e280>{number = 1, name = main}
      2018-03-20 18:01:35.928257+0800 GCD[55856:2568766] [After]: main ---<NSThread: 0x60000006e280>{number = 1, name = main}
      2018-03-20 18:01:35.928274+0800 GCD[55856:2571380] [After]: global ---<NSThread: 0x60c00007e280>{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---<NSThread: 0x60c000262bc0>{number = 1, name = main}
      2018-03-20 18:05:42.459417+0800 GCD[56041:2574512] 1---<NSThread: 0x60c00027f840>{number = 3, name = (null)}
      2018-03-20 18:05:42.459504+0800 GCD[56041:2574499] 4---<NSThread: 0x6080002786c0>{number = 7, name = (null)}
      2018-03-20 18:05:42.459504+0800 GCD[56041:2574502] 3---<NSThread: 0x604000270e00>{number = 4, name = (null)}
      2018-03-20 18:05:42.459506+0800 GCD[56041:2574500] 5---<NSThread: 0x604000270c00>{number = 6, name = (null)}
      2018-03-20 18:05:42.459521+0800 GCD[56041:2574501] 2---<NSThread: 0x608000278a00>{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---<NSThread: 0x60c000065740>{number = 1, name = main}
      2018-03-20 18:07:35.989109+0800 GCD[56083:2576141] 1---<NSThread: 0x60c000065740>{number = 1, name = main}
      2018-03-20 18:07:37.990556+0800 GCD[56083:2576141] 2---<NSThread: 0x60c000065740>{number = 1, name = main}
      2018-03-20 18:07:39.992050+0800 GCD[56083:2576141] 3---<NSThread: 0x60c000065740>{number = 1, name = main}
      2018-03-20 18:07:41.993583+0800 GCD[56083:2576141] 4---<NSThread: 0x60c000065740>{number = 1, name = main}
      2018-03-20 18:07:43.995163+0800 GCD[56083:2576141] 5---<NSThread: 0x60c000065740>{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---<NSThread: 0x60800006ce00>{number = 4, name = (null)}
      2018-03-20 18:09:49.307608+0800 GCD[56083:2577770] 1---<NSThread: 0x60400007fac0>{number = 3, name = (null)}
      2018-03-20 18:09:51.309380+0800 GCD[56083:2576141] 3---<NSThread: 0x60c000065740>{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---<NSThread: 0x60800006ce00>{number = 4, name = (null)}
      2018-03-20 18:09:58.331259+0800 GCD[56083:2577770] 2---<NSThread: 0x60400007fac0>{number = 3, name = (null)}
      2018-03-20 18:09:58.331676+0800 GCD[56083:2576141] group notify : <NSThread: 0x60c000065740>{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---<NSThread: 0x600000260780>{number = 5, name = (null)}
      2018-03-20 18:13:02.524335+0800 GCD[56083:2577781] 2---<NSThread: 0x60000007fd40>{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 --- <NSThread: 0x60c000078880>{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 = <OS_dispatch_semaphore: 0x60c000084510>
      2018-03-20 18:16:21.561717+0800 GCD[56217:2582805] i = 1 semaphore = <OS_dispatch_semaphore: 0x60c000084510>
      2018-03-20 18:16:21.561999+0800 GCD[56217:2582803] i = 2 semaphore = <OS_dispatch_semaphore: 0x60c000084510>
      2018-03-20 18:16:21.562277+0800 GCD[56217:2582804] i = 3 semaphore = <OS_dispatch_semaphore: 0x60c000084510>
      2018-03-20 18:16:21.562508+0800 GCD[56217:2582812] i = 4 semaphore = <OS_dispatch_semaphore: 0x60c000084510>
      2018-03-20 18:16:21.562745+0800 GCD[56217:2582823] i = 5 semaphore = <OS_dispatch_semaphore: 0x60c000084510>
      2018-03-20 18:16:21.562979+0800 GCD[56217:2582824] i = 6 semaphore = <OS_dispatch_semaphore: 0x60c000084510>
      2018-03-20 18:16:21.563213+0800 GCD[56217:2582825] i = 7 semaphore = <OS_dispatch_semaphore: 0x60c000084510>
      2018-03-20 18:16:21.563442+0800 GCD[56217:2582826] i = 8 semaphore = <OS_dispatch_semaphore: 0x60c000084510>
      2018-03-20 18:16:21.563671+0800 GCD[56217:2582827] i = 9 semaphore = <OS_dispatch_semaphore: 0x60c000084510>
      
    • 并发控制通过信号实现:
      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

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