美文网首页
GCD多线程应用

GCD多线程应用

作者: a315c2a13dc5 | 来源:发表于2017-08-09 23:48 被阅读0次

    概念

    在GCD中有两个重要的概念:任务和队列。

    任务

    所要执行的操作。任务有两种执行方式:同步执行和异步执行。

    • 同步执行:
      1. 会阻塞当前线程,直到任务执行完成才会返回当前线程继续运行
      2. 不具备开启新线程的能力
    • 异步执行:
      1. 不会阻塞当前线程,会立即返回当前线程继续运行
      2. 具备开启新线程的能力

    队列

    用于存放任务。队列有两种:串行队列和并发队列。

    • 串行队列:

      1. 任务执行遵循先进先出的顺序,下一个任务在上一个任务执行完成后开始执行
      2. 创建方式(两种)
      dispatch_queue_t serialQueue = dispatch_queue_create("com.apress.mySerialQueue", nil) ;
      dispatch_queue_t serialQueue = dispatch_queue_create("com.apress.mySerialQueue", DISPATCH_QUEUE_SERIAL) ;
      
    • 并发队列:

      1. 任务执行遵循先进先出的顺序,下一个任务可以在上一个任务执行完成前开始执行
      2. 创建方式
      dispatch_queue_t concurrentQueue = dispatch_queue_create("com.appress.myConcurrentQueue",DISPATCH_QUEUE_CONCURRENT) ;
      
      1. 系统提供了四种全局的并发队列,这些队列通过优先级加以区别。高优先级队列中的任务会比在默认或低优先级队列中的任务先执行,而默认级别队列的优先级又高于低优先级队列。被设置成后台级别的队列,它会等待所有比它级别高的队列中的任务执行完或CPU空闲的时候才会执行自己的任务
      dispatch_queue_t  concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) ;
      
      字段 优先级
      DISPATCH_QUEUE_PRIORITY_HIGH 高优先级
      DISPATCH_QUEUE_PRIORITY_DEFAULT 默认优先级
      DISPATCH_QUEUE_PRIORITY_LOW 低优先级
      DISPATCH_QUEUE_PRIORITY_BACKGROUND 后台级别
    • 主队列:
      除了串行队列和并发队列,还有一种特殊的队列——主队列。

      1. 是串行队列
      2. 所有放在主队列中的任务都会放到主线程中执行
      3. 可通过dispatch_get_main_queue()获得

    GCD的多线程使用

    使用步骤

    1. 创建队列
    2. 向队列中添加任务:
      • 通过dispatch_async进行异步添加
      • 通过dispatch_sync进行同步添加

    使用方式

    由于存在不同的队列和任务执行方式,因此有多种组合方式来使用。

    1. 并发队列+同步执行
    - (void)test {
        NSLog(@"=============begin") ;
        dispatch_queue_t myQueue = dispatch_queue_create("com.appress.myQueue",DISPATCH_QUEUE_CONCURRENT) ;
        dispatch_sync(myQueue, ^{
            for(int i = 0; i < 2; i++) {
                NSLog(@"1=========%@",[NSThread currentThread]) ;
            }
        }) ;
        dispatch_sync(myQueue, ^{
            for(int i = 0; i < 2; i++) {
                NSLog(@"2=========%@",[NSThread currentThread]) ;
            }
        }) ;
        dispatch_sync(myQueue, ^{
            for(int i = 0; i < 2; i++) {
                NSLog(@"3=========%@",[NSThread currentThread]) ;
            }
        }) ;
        NSLog(@"=============end") ;
    }
    

    打印结果为:

    2017-05-03 14:59:35.976 test[1022:28719] =============begin
    2017-05-03 14:59:35.977 test[1022:28719] 1=========<NSThread: 0x600000071240>{number = 1, name = main}
    2017-05-03 14:59:35.977 test[1022:28719] 1=========<NSThread: 0x600000071240>{number = 1, name = main}
    2017-05-03 14:59:35.977 test[1022:28719] 2=========<NSThread: 0x600000071240>{number = 1, name = main}
    2017-05-03 14:59:35.977 test[1022:28719] 2=========<NSThread: 0x600000071240>{number = 1, name = main}
    2017-05-03 14:59:35.977 test[1022:28719] 3=========<NSThread: 0x600000071240>{number = 1, name = main}
    2017-05-03 14:59:35.977 test[1022:28719] 3=========<NSThread: 0x600000071240>{number = 1, name = main}
    2017-05-03 14:59:35.978 test[1022:28719] =============end
    
    • 不会开启新线程,而是在当前线程执行
    • 任务按照顺序一个一个执行
    • 会阻塞当前线程
    1. 并发队列+异步执行
    - (void)test {
        NSLog(@"=============begin") ;
        dispatch_queue_t myQueue = dispatch_queue_create("com.appress.myQueue",DISPATCH_QUEUE_CONCURRENT) ;
        dispatch_async(myQueue, ^{
            for(int i = 0; i < 2; i++) {
                NSLog(@"1=========%@",[NSThread currentThread]) ;
            }
        }) ;
        dispatch_async(myQueue, ^{
            for(int i = 0; i < 2; i++) {
                NSLog(@"2=========%@",[NSThread currentThread]) ;
            }
        }) ;
        dispatch_async(myQueue, ^{
            for(int i = 0; i < 2; i++) {
                NSLog(@"3=========%@",[NSThread currentThread]) ;
            }
        }) ;
        NSLog(@"=============end") ;
    }
    

    打印结果为:

    2017-05-03 15:04:37.047 test[1064:39634] =============begin
    2017-05-03 15:04:37.047 test[1064:39634] =============end
    2017-05-03 15:04:37.048 test[1064:39685] 2=========<NSThread: 0x60800007bc00>{number = 4, name = (null)}
    2017-05-03 15:04:37.048 test[1064:39690] 1=========<NSThread: 0x60800007bd00>{number = 3, name = (null)}
    2017-05-03 15:04:37.048 test[1064:39684] 3=========<NSThread: 0x60800007bfc0>{number = 5, name = (null)}
    2017-05-03 15:04:37.048 test[1064:39685] 2=========<NSThread: 0x60800007bc00>{number = 4, name = (null)}
    2017-05-03 15:04:37.048 test[1064:39690] 1=========<NSThread: 0x60800007bd00>{number = 3, name = (null)}
    2017-05-03 15:04:37.049 test[1064:39684] 3=========<NSThread: 0x60800007bfc0>{number = 5, name = (null)}
    
    • 开启了多个新线程,并且在各自的新线程中执行
    • 任务交替着同时执行
    • 不会阻塞当前线程
    1. 串行队列+同步执行
    - (void)test {
        NSLog(@"=============begin") ;
        dispatch_queue_t myQueue = dispatch_queue_create("com.appress.myQueue",nil) ;
        dispatch_sync(myQueue, ^{
            for(int i = 0; i < 2; i++) {
                NSLog(@"1=========%@",[NSThread currentThread]) ;
            }
        }) ;
        dispatch_sync(myQueue, ^{
            for(int i = 0; i < 2; i++) {
                NSLog(@"2=========%@",[NSThread currentThread]) ;
            }
        }) ;
        dispatch_sync(myQueue, ^{
            for(int i = 0; i < 2; i++) {
                NSLog(@"3=========%@",[NSThread currentThread]) ;
            }
        }) ;
        NSLog(@"=============end") ;
    }
    

    打印结果为:

    2017-05-03 15:10:33.497 test[1133:50233] =============begin
    2017-05-03 15:10:33.497 test[1133:50233] 1=========<NSThread: 0x608000063800>{number = 1, name = main}
    2017-05-03 15:10:33.498 test[1133:50233] 1=========<NSThread: 0x608000063800>{number = 1, name = main}
    2017-05-03 15:10:33.498 test[1133:50233] 2=========<NSThread: 0x608000063800>{number = 1, name = main}
    2017-05-03 15:10:33.498 test[1133:50233] 2=========<NSThread: 0x608000063800>{number = 1, name = main}
    2017-05-03 15:10:33.499 test[1133:50233] 3=========<NSThread: 0x608000063800>{number = 1, name = main}
    2017-05-03 15:10:33.499 test[1133:50233] 3=========<NSThread: 0x608000063800>{number = 1, name = main}
    2017-05-03 15:10:33.499 test[1133:50233] =============end
    
    • 不会开启新线程,而是在当前线程执行
    • 任务按照顺序一个一个执行
    • 会阻塞当前线程
    1. 串行队列+异步执行
    - (void)test {
        NSLog(@"=============begin") ;
        dispatch_queue_t myQueue = dispatch_queue_create("com.appress.myQueue",nil) ;
        dispatch_async(myQueue, ^{
            for(int i = 0; i < 2; i++) {
                NSLog(@"1=========%@",[NSThread currentThread]) ;
            }
        }) ;
        dispatch_async(myQueue, ^{
            for(int i = 0; i < 2; i++) {
                NSLog(@"2=========%@",[NSThread currentThread]) ;
            }
        }) ;
        dispatch_async(myQueue, ^{
            for(int i = 0; i < 2; i++) {
                NSLog(@"3=========%@",[NSThread currentThread]) ;
            }
        }) ;
        NSLog(@"=============end") ;
    }
    

    打印结果为:

    2017-05-03 15:13:35.786 test[1168:56495] =============begin
    2017-05-03 15:13:35.787 test[1168:56495] =============end
    2017-05-03 15:13:35.787 test[1168:56601] 1=========<NSThread: 0x608000270200>{number = 3, name = (null)}
    2017-05-03 15:13:35.787 test[1168:56601] 1=========<NSThread: 0x608000270200>{number = 3, name = (null)}
    2017-05-03 15:13:35.787 test[1168:56601] 2=========<NSThread: 0x608000270200>{number = 3, name = (null)}
    2017-05-03 15:13:35.787 test[1168:56601] 2=========<NSThread: 0x608000270200>{number = 3, name = (null)}
    2017-05-03 15:13:35.788 test[1168:56601] 3=========<NSThread: 0x608000270200>{number = 3, name = (null)}
    2017-05-03 15:13:35.788 test[1168:56601] 3=========<NSThread: 0x608000270200>{number = 3, name = (null)}
    
    • 开启了一个新线程,所有任务都在该新线程中执行
    • 任务按照顺序一个一个执行
    • 不会阻塞当前线程
    1. 主队列+同步执行
    NSLog(@"=============begin") ;
        dispatch_queue_t myQueue = dispatch_get_main_queue() ;
        dispatch_sync(myQueue, ^{
            for(int i = 0; i < 2; i++) {
                NSLog(@"1=========%@",[NSThread currentThread]) ;
            }
        }) ;
        dispatch_sync(myQueue, ^{
            for(int i = 0; i < 2; i++) {
                NSLog(@"2=========%@",[NSThread currentThread]) ;
            }
        }) ;
        dispatch_sync(myQueue, ^{
            for(int i = 0; i < 2; i++) {
                NSLog(@"3=========%@",[NSThread currentThread]) ;
            }
        }) ;
        NSLog(@"=============end") ;
    
    

    如果在主线程中采用该方式会出现互等卡住的情况。

    在子线程中执行的打印结果为:

    2017-05-03 15:34:40.630 test[1279:89558] =============begin
    2017-05-03 15:34:40.634 test[1279:89501] 1=========<NSThread: 0x60000006e3c0>{number = 1, name = main}
    2017-05-03 15:34:40.635 test[1279:89501] 1=========<NSThread: 0x60000006e3c0>{number = 1, name = main}
    2017-05-03 15:34:40.636 test[1279:89501] 2=========<NSThread: 0x60000006e3c0>{number = 1, name = main}
    2017-05-03 15:34:40.636 test[1279:89501] 2=========<NSThread: 0x60000006e3c0>{number = 1, name = main}
    2017-05-03 15:34:40.636 test[1279:89501] 3=========<NSThread: 0x60000006e3c0>{number = 1, name = main}
    2017-05-03 15:34:40.636 test[1279:89501] 3=========<NSThread: 0x60000006e3c0>{number = 1, name = main}
    2017-05-03 15:34:40.637 test[1279:89558] =============end
    
    • 在主线程中执行
    • 任务按照顺序一个一个执行
    • 会阻塞当前线程
    1. 主队列+异步执行
    - (void)test {
        NSLog(@"=============begin") ;
        dispatch_queue_t myQueue = dispatch_get_main_queue() ;
        dispatch_async(myQueue, ^{
            for(int i = 0; i < 2; i++) {
                NSLog(@"1=========%@",[NSThread currentThread]) ;
            }
        }) ;
        dispatch_async(myQueue, ^{
            for(int i = 0; i < 2; i++) {
                NSLog(@"2=========%@",[NSThread currentThread]) ;
            }
        }) ;
        dispatch_async(myQueue, ^{
            for(int i = 0; i < 2; i++) {
                NSLog(@"3=========%@",[NSThread currentThread]) ;
            }
        }) ;
        NSLog(@"=============end") ;
    }
    

    打印结果为:

    2017-05-03 15:36:10.336 test[1312:93448] =============begin
    2017-05-03 15:36:10.337 test[1312:93448] =============end
    2017-05-03 15:36:10.347 test[1312:93448] 1=========<NSThread: 0x600000064c80>{number = 1, name = main}
    2017-05-03 15:36:10.348 test[1312:93448] 1=========<NSThread: 0x600000064c80>{number = 1, name = main}
    2017-05-03 15:36:10.352 test[1312:93448] 2=========<NSThread: 0x600000064c80>{number = 1, name = main}
    2017-05-03 15:36:10.358 test[1312:93448] 2=========<NSThread: 0x600000064c80>{number = 1, name = main}
    2017-05-03 15:36:10.359 test[1312:93448] 3=========<NSThread: 0x600000064c80>{number = 1, name = main}
    2017-05-03 15:36:10.359 test[1312:93448] 3=========<NSThread: 0x600000064c80>{number = 1, name = main}
    
    • 在主线程中执行
    • 任务按照顺序一个一个执行
    • 不会阻塞当前线程

    总结如下:

    队列 并行队列 串行队列 主队列
    同步(sync) 没有开启新线程,串行执行任务 没有开启新线程,串行执行任务 没有开启新线程,串行执行任务
    异步(async) 有开启新线程,并发执行任务 有开启新线程,串行执行任务 没有开启新线程,串行执行任务

    当任务队列为非主队列时,只有异步执行才会开启新线程。如果是并发队列,会开启多条线程,如果是串行队列, 只会开启一条线程。 其他情况下(包括主队列) 都不会开启新线程,并且是串行执行任务。

    GCD的其他使用

    GCD 栅栏函数

    在异步执行任务的过程中,有时候需要控制任务执行的顺序:在第一组任务执行完成后再执行第二组任务,可以通过GCD的栅栏函数dispatch_barrier_async来实现。当栅栏函数执行完成后才会执行后面的任务。

    使用

    添加栅栏函数前:

    - (void)test {
        NSLog(@"=============begin") ;
        dispatch_queue_t myQueue = dispatch_queue_create("com.appress.myQueue",DISPATCH_QUEUE_CONCURRENT) ;
        dispatch_async(myQueue, ^{
            for(int i = 0; i < 3; i++) {
                NSLog(@"1=========%@",[NSThread currentThread]) ;
            }
        }) ;
        dispatch_async(myQueue, ^{
            for(int i = 0; i < 3; i++) {
                NSLog(@"2=========%@",[NSThread currentThread]) ;
            }
        }) ;
    //    dispatch_barrier_async(myQueue, ^{
    //        NSLog(@"++++++++++++++++++++++++++++++++++++++++") ;
    //    }) ;
        dispatch_async(myQueue, ^{
            for(int i = 0; i < 3; i++) {
                NSLog(@"3=========%@",[NSThread currentThread]) ;
            }
        }) ;
        dispatch_async(myQueue, ^{
            for(int i = 0; i < 3; i++) {
                NSLog(@"4=========%@",[NSThread currentThread]) ;
            }
        }) ;
        NSLog(@"=============end") ;
    }
    

    打印结果为:

    2017-05-08 15:37:00.970 test[14150:286911] =============begin
    2017-05-08 15:37:00.970 test[14150:286911] =============end
    2017-05-08 15:37:00.970 test[14150:286950] 2=========<NSThread: 0x60000026b480>{number = 4, name = (null)}
    2017-05-08 15:37:00.970 test[14150:286951] 1=========<NSThread: 0x608000267680>{number = 3, name = (null)}
    2017-05-08 15:37:00.970 test[14150:286971] 4=========<NSThread: 0x60000026bac0>{number = 6, name = (null)}
    2017-05-08 15:37:00.970 test[14150:286953] 3=========<NSThread: 0x60000026b4c0>{number = 5, name = (null)}
    2017-05-08 15:37:00.971 test[14150:286950] 2=========<NSThread: 0x60000026b480>{number = 4, name = (null)}
    2017-05-08 15:37:00.971 test[14150:286951] 1=========<NSThread: 0x608000267680>{number = 3, name = (null)}
    2017-05-08 15:37:00.971 test[14150:286971] 4=========<NSThread: 0x60000026bac0>{number = 6, name = (null)}
    2017-05-08 15:37:00.971 test[14150:286953] 3=========<NSThread: 0x60000026b4c0>{number = 5, name = (null)}
    2017-05-08 15:37:00.971 test[14150:286950] 2=========<NSThread: 0x60000026b480>{number = 4, name = (null)}
    2017-05-08 15:37:00.971 test[14150:286951] 1=========<NSThread: 0x608000267680>{number = 3, name = (null)}
    2017-05-08 15:37:00.972 test[14150:286953] 3=========<NSThread: 0x60000026b4c0>{number = 5, name = (null)}
    2017-05-08 15:37:00.972 test[14150:286971] 4=========<NSThread: 0x60000026bac0>{number = 6, name = (null)}
    

    添加栅栏函数后:

    - (void)test {
        NSLog(@"=============begin") ;
        dispatch_queue_t myQueue = dispatch_queue_create("com.appress.myQueue",DISPATCH_QUEUE_CONCURRENT) ;
        dispatch_async(myQueue, ^{
            for(int i = 0; i < 3; i++) {
                NSLog(@"1=========%@",[NSThread currentThread]) ;
            }
        }) ;
        dispatch_async(myQueue, ^{
            for(int i = 0; i < 3; i++) {
                NSLog(@"2=========%@",[NSThread currentThread]) ;
            }
        }) ;
        dispatch_barrier_async(myQueue, ^{
            NSLog(@"++++++++++++++++++++++++++++++++++++++++") ;
        }) ;
        dispatch_async(myQueue, ^{
            for(int i = 0; i < 3; i++) {
                NSLog(@"3=========%@",[NSThread currentThread]) ;
            }
        }) ;
        dispatch_async(myQueue, ^{
            for(int i = 0; i < 3; i++) {
                NSLog(@"4=========%@",[NSThread currentThread]) ;
            }
        }) ;
        NSLog(@"=============end") ;
    }
    

    打印结果为:

    2017-05-08 16:02:47.255 test[14241:316852] =============begin
    2017-05-08 16:02:47.256 test[14241:316852] =============end
    2017-05-08 16:02:47.256 test[14241:316986] 1=========<NSThread: 0x60000006f440>{number = 3, name = (null)}
    2017-05-08 16:02:47.256 test[14241:316983] 2=========<NSThread: 0x60800006c2c0>{number = 4, name = (null)}
    2017-05-08 16:02:47.256 test[14241:316986] 1=========<NSThread: 0x60000006f440>{number = 3, name = (null)}
    2017-05-08 16:02:47.256 test[14241:316983] 2=========<NSThread: 0x60800006c2c0>{number = 4, name = (null)}
    2017-05-08 16:02:47.256 test[14241:316986] 1=========<NSThread: 0x60000006f440>{number = 3, name = (null)}
    2017-05-08 16:02:47.257 test[14241:316983] 2=========<NSThread: 0x60800006c2c0>{number = 4, name = (null)}
    2017-05-08 16:02:47.257 test[14241:316983] ++++++++++++++++++++++++++++++++++++++++
    2017-05-08 16:02:47.257 test[14241:316983] 3=========<NSThread: 0x60800006c2c0>{number = 4, name = (null)}
    2017-05-08 16:02:47.257 test[14241:316986] 4=========<NSThread: 0x60000006f440>{number = 3, name = (null)}
    2017-05-08 16:02:47.257 test[14241:316983] 3=========<NSThread: 0x60800006c2c0>{number = 4, name = (null)}
    2017-05-08 16:02:47.257 test[14241:316986] 4=========<NSThread: 0x60000006f440>{number = 3, name = (null)}
    2017-05-08 16:02:47.257 test[14241:316983] 3=========<NSThread: 0x60800006c2c0>{number = 4, name = (null)}
    2017-05-08 16:02:47.258 test[14241:316986] 4=========<NSThread: 0x60000006f440>{number = 3, name = (null)}
    
    

    注意

    • 栅栏函数不能使用全局的并发队列。

    GCD的迭代

    使用

    dispatch_apply(迭代次数, 线程队列(并发队列), ^(size_t index索引) {
           执行任务 ;
    }) ;
    

    注意

    • 开启了子线程来执行任务
    • 迭代不是按照顺序的

    GCD队列组

    异步执行多个耗时操作,当所有操作都执行完毕后再执行某一操作。可以通过使用GCD队列组来实现。

    使用

    NSLog(@"===============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, ^{
        for(int i = 0 ; i < 4 ; i ++) {
            NSLog(@"1===============%@",[NSThread currentThread]) ;
        }
    }) ;
    dispatch_group_async(group, queue, ^{
        for(int i = 0 ; i < 4 ; i ++) {
            NSLog(@"2===============%@",[NSThread currentThread]) ;
        }
    }) ;
    dispatch_group_async(group, queue, ^{
        for(int i = 0 ; i < 4 ; i ++) {
            NSLog(@"3===============%@",[NSThread currentThread]) ;
        }
    }) ;
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"===============end") ;
    }) ;
    
    

    打印结果为:

    2017-08-08 13:36:21.124 GCD[3643:200121] ===============begin
    2017-08-08 13:36:21.125 GCD[3643:200159] 1===============<NSThread: 0x60000007f2c0>{number = 3, name = (null)}
    2017-08-08 13:36:21.125 GCD[3643:200156] 3===============<NSThread: 0x608000267100>{number = 5, name = (null)}
    2017-08-08 13:36:21.125 GCD[3643:200157] 2===============<NSThread: 0x60800007cac0>{number = 4, name = (null)}
    2017-08-08 13:36:21.125 GCD[3643:200159] 1===============<NSThread: 0x60000007f2c0>{number = 3, name = (null)}
    2017-08-08 13:36:21.125 GCD[3643:200156] 3===============<NSThread: 0x608000267100>{number = 5, name = (null)}
    2017-08-08 13:36:21.125 GCD[3643:200157] 2===============<NSThread: 0x60800007cac0>{number = 4, name = (null)}
    2017-08-08 13:36:21.125 GCD[3643:200159] 1===============<NSThread: 0x60000007f2c0>{number = 3, name = (null)}
    2017-08-08 13:36:21.125 GCD[3643:200156] 3===============<NSThread: 0x608000267100>{number = 5, name = (null)}
    2017-08-08 13:36:21.126 GCD[3643:200157] 2===============<NSThread: 0x60800007cac0>{number = 4, name = (null)}
    2017-08-08 13:36:21.126 GCD[3643:200159] 1===============<NSThread: 0x60000007f2c0>{number = 3, name = (null)}
    2017-08-08 13:36:21.126 GCD[3643:200156] 3===============<NSThread: 0x608000267100>{number = 5, name = (null)}
    2017-08-08 13:36:21.126 GCD[3643:200157] 2===============<NSThread: 0x60800007cac0>{number = 4, name = (null)}
    2017-08-08 13:36:21.132 GCD[3643:200121] ===============end
    

    如果dispatch_group_async的操作中有延时回调,那么在所有回调完成前就会执行dispatch_group_notify

    typedef void (^resultBlock) () ;
    @implementation ViewController
    - (void)viewDidLoad {
        [super viewDidLoad];
        NSLog(@"===============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, ^{
            [self testWithBlock:^{
                for(int i = 0 ; i < 4 ; i ++) {
                    NSLog(@"1===============%@",[NSThread currentThread]) ;
                }
            }] ;
        }) ;
        dispatch_group_async(group, queue, ^{
            [self testWithBlock:^{
                for(int i = 0 ; i < 4 ; i ++) {
                    NSLog(@"2===============%@",[NSThread currentThread]) ;
                }
            }] ;
    
        }) ;
        dispatch_group_async(group, queue, ^{
            [self testWithBlock:^{
                for(int i = 0 ; i < 4 ; i ++) {
                    NSLog(@"3===============%@",[NSThread currentThread]) ;
                }
            }] ;
        }) ;
        dispatch_group_notify(group, dispatch_get_main_queue(), ^{
            NSLog(@"===============end") ;
        }) ;
    }
    
    - (void)testWithBlock:(resultBlock)block {
        dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0*NSEC_PER_SEC)) ;
        dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_CONCURRENT) ;
        dispatch_after(time, queue, ^{
            block() ;
        }) ;
    }
    
    

    打印结果为:

    2017-08-08 14:40:25.811 GCD[16467:291922] ===============begin
    2017-08-08 14:40:26.048 GCD[16467:291922] ===============end
    2017-08-08 14:40:28.007 GCD[16467:291980] 1===============<NSThread: 0x60000007c900>{number = 3, name = (null)}
    2017-08-08 14:40:28.007 GCD[16467:291979] 3===============<NSThread: 0x608000262100>{number = 4, name = (null)}
    2017-08-08 14:40:28.007 GCD[16467:291982] 2===============<NSThread: 0x60000007c340>{number = 5, name = (null)}
    2017-08-08 14:40:28.008 GCD[16467:291979] 3===============<NSThread: 0x608000262100>{number = 4, name = (null)}
    2017-08-08 14:40:28.008 GCD[16467:291980] 1===============<NSThread: 0x60000007c900>{number = 3, name = (null)}
    2017-08-08 14:40:28.008 GCD[16467:291982] 2===============<NSThread: 0x60000007c340>{number = 5, name = (null)}
    2017-08-08 14:40:28.008 GCD[16467:291979] 3===============<NSThread: 0x608000262100>{number = 4, name = (null)}
    2017-08-08 14:40:28.008 GCD[16467:291980] 1===============<NSThread: 0x60000007c900>{number = 3, name = (null)}
    2017-08-08 14:40:28.008 GCD[16467:291982] 2===============<NSThread: 0x60000007c340>{number = 5, name = (null)}
    2017-08-08 14:40:28.009 GCD[16467:291979] 3===============<NSThread: 0x608000262100>{number = 4, name = (null)}
    2017-08-08 14:40:28.009 GCD[16467:291980] 1===============<NSThread: 0x60000007c900>{number = 3, name = (null)}
    2017-08-08 14:40:28.009 GCD[16467:291982] 2===============<NSThread: 0x60000007c340>{number = 5, name = (null)}
    
    

    通过dispatch_group_enter(group)dispatch_group_leave(group)的配合使用来解决这个问题。

    typedef void (^resultBlock) () ;
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        NSLog(@"===============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_group_async(group, queue, ^{
            [self testWithBlock:^{
                for(int i = 0 ; i < 4 ; i ++) {
                    NSLog(@"1===============%@",[NSThread currentThread]) ;
                }
                dispatch_group_leave(group) ;
            }] ;
        }) ;
        dispatch_group_enter(group) ;
        dispatch_group_async(group, queue, ^{
            [self testWithBlock:^{
                for(int i = 0 ; i < 4 ; i ++) {
                    NSLog(@"2===============%@",[NSThread currentThread]) ;
                }
                dispatch_group_leave(group) ;
            }] ;
    
        }) ;
        dispatch_group_enter(group) ;
        dispatch_group_async(group, queue, ^{
            [self testWithBlock:^{
                for(int i = 0 ; i < 4 ; i ++) {
                    NSLog(@"3===============%@",[NSThread currentThread]) ;
                }
                dispatch_group_leave(group) ;
            }] ;
        }) ;
        dispatch_group_notify(group, dispatch_get_main_queue(), ^{
            NSLog(@"===============end") ;
        }) ;
    }
    
    - (void)testWithBlock:(resultBlock)block {
        dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0*NSEC_PER_SEC)) ;
        dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_CONCURRENT) ;
        dispatch_after(time, queue, ^{
            block() ;
        }) ;
    }
    
    @end
    
    

    打印结果为:

    2017-08-08 15:03:07.867 GCD[16548:311040] ===============begin
    2017-08-08 15:03:09.868 GCD[16548:311101] 2===============<NSThread: 0x6000000773c0>{number = 5, name = (null)}
    2017-08-08 15:03:09.868 GCD[16548:311098] 3===============<NSThread: 0x60000007ab40>{number = 3, name = (null)}
    2017-08-08 15:03:09.868 GCD[16548:311099] 1===============<NSThread: 0x608000071d80>{number = 4, name = (null)}
    2017-08-08 15:03:09.869 GCD[16548:311101] 2===============<NSThread: 0x6000000773c0>{number = 5, name = (null)}
    2017-08-08 15:03:09.869 GCD[16548:311098] 3===============<NSThread: 0x60000007ab40>{number = 3, name = (null)}
    2017-08-08 15:03:09.869 GCD[16548:311099] 1===============<NSThread: 0x608000071d80>{number = 4, name = (null)}
    2017-08-08 15:03:09.869 GCD[16548:311101] 2===============<NSThread: 0x6000000773c0>{number = 5, name = (null)}
    2017-08-08 15:03:09.869 GCD[16548:311098] 3===============<NSThread: 0x60000007ab40>{number = 3, name = (null)}
    2017-08-08 15:03:09.869 GCD[16548:311099] 1===============<NSThread: 0x608000071d80>{number = 4, name = (null)}
    2017-08-08 15:03:09.869 GCD[16548:311101] 2===============<NSThread: 0x6000000773c0>{number = 5, name = (null)}
    2017-08-08 15:03:09.870 GCD[16548:311098] 3===============<NSThread: 0x60000007ab40>{number = 3, name = (null)}
    2017-08-08 15:03:09.870 GCD[16548:311099] 1===============<NSThread: 0x608000071d80>{number = 4, name = (null)}
    2017-08-08 15:03:09.870 GCD[16548:311040] ===============end
    
    

    通过这种方法可以解决诸如:多个网络请求全部完成以后再进行某项操作的问题。

    相关文章

      网友评论

          本文标题:GCD多线程应用

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