一、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上任务完成,或者等待时间超过设置的超时时间会结束等待。
- (void)groupFunction
{
dispatch_queue_t queue = dispatch_queue_create("com.hkshen.csdn", DISPATCH_QUEUE_CONCURRENT);
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_queue_t concurrentQueue = dispatch_queue_create("com.hkshen.csdn", DISPATCH_QUEUE_CONCURRENT);
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(@”第二步”)执行完毕,这样程序就崩溃了。