一、GCD的队列(dispatch_queue_t)分哪两种类型?

GCD队列分两种类型,串行队列Serial Dispatch Queue和并行队列Concurrent Dispatch Queue。

队列可以接受任务,并且按照任务先到先执行的顺序来执行。



二、如何用GCD同步若干个异步调用?(如根据若干个url异步加载多张图片,然后在都下载完成后合成一张整图)?

使用dispatch_group。

dispatch_group_notify:当提交到队列dispatch_queue_t queue上的所有任务执行完毕时会执行dispatch_group_notify里的dispatch_block_t block的代码。

dispatch_group_wait:和dispatch_group_notify功能类似(多了一个dispatch_time_t参数可以设置超时时间),在group上任务完成前,dispatch_group_wait会阻塞当前线程(所以不能放在主线程调用)一直等待;当group上任务完成,或者等待时间超过设置的超时时间会结束等待。

- ( dispatch_group_t group = dispatch_group_create();
    dispatch_group_async(group, queue, ^{
        NSLog(@"加载图片1");
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"加载图片2");
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"加载图片3");
    });
dispatch_group_notify(group, dispatch_get_main_queue, ^{
        NSLog(@"各部分图片加载完成,并且在主线程合并图片");
    });
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        dispatch_group_wait(group, dispatch_time(DISPATCH_TIME_NOW, 9 * NSEC_PER_SEC));
        NSLog(@"各部分图片加载完成");
    });
}


详细:http://www.jianshu.com/p/228403206664




三、dispatch_barrier_async的作用是什么?

 dispatch_async(concurrentQueue, ^{
        sleep(1);
        NSLog(@"任务1");
    });
    dispatch_async(concurrentQueue, ^{
        NSLog(@"任务2");
    });
    dispatch_async(concurrentQueue, ^{
        NSLog(@"任务3");
    });
    
    dispatch_barrier_async(concurrentQueue, ^{
        NSLog(@"虽然是并行队列(concurrentQueue),dispatch_barrier_async会等提交到concurrentQueue的任务全部执行完了后再执行dispatch_barrier_async提交的任务。");
    });
    
    dispatch_async(concurrentQueue, ^{
        NSLog(@"任务4");
    });
    dispatch_async(concurrentQueue, ^{
        NSLog(@"任务5");
    });

打印:

2017-09-08 15:24:09.419 UISkeletonStoryboard[35596:3143321] 任务2
2017-09-08 15:24:09.419 UISkeletonStoryboard[35596:3143320] 任务3
2017-09-08 15:24:10.422 UISkeletonStoryboard[35596:3143323] 任务1
2017-09-08 15:24:10.423 UISkeletonStoryboard[35596:3143323] 虽然是并行队列(concurrentQueue),dispatch_barrier_async会等提交到concurrentQueue的任务全部执行完了后再执行dispatch_barrier_async提交的任务。
2017-09-08 15:24:10.423 UISkeletonStoryboard[35596:3143323] 任务4
2017-09-08 15:24:10.423 UISkeletonStoryboard[35596:3143320] 任务5



1、dispatch_barrier_async作用是在并行队列中,等待前面三个操作并行操作完成。
2、然后执行dispatch_barrier_async中的操作,(虽然是并行队列,但现在就只会执行这一个操作)。
3、最后该并行队列恢复原有执行状态,继续并行执行。







四、苹果为什么要废弃dispatch_get_current_queue?


dispatch_get_current_queue容易造成死锁。




五、以下代码运行结果如何?

- (void)viewDidLoad
{
    [super viewDidLoad];
    NSLog(@"第一步");
    dispatch_sync(dispatch_get_main_queue(), ^{
        NSLog(@"第二步");
    });
    NSLog(@"第三步");
}


输出:第一步。

然后程序崩溃,EXC_BAD_INSTRUCTION(code=EXC_l386_INVOP,subcode=0x0)。
因为dispatch_get_main_queue()得到一个串行队列,串行队列的特点: 一次只调度一个任务,队列中的任务一个接着一个地执行(一个任务执行完毕后,再执行下一个任务)。

同步(sync) 操作,它会阻塞当前线程并等待 block 中的任务执行完毕,然后当前线程才会继续往下运行。

dispatch_sync提交一个打印任务NSLog(@”第二步”)到主线程关联的串行队列中,主线程关联的串行队列现在有一个viewDidLoad任务,打印任务NSLog(@”第二步”)排在viewDidLoad后面,根据队列FIFO(先进先出)的原则,打印任务NSLog(@”第二步”)想要得到执行必须等到viewDidLoad执行完毕后才能得到执行,但是viewDidLoad想要执行完毕必须要等打印任务NSLog(@”第二步”)执行完毕,这样程序就崩溃了。