关于GCD就不多介绍了,Apple封装好的系统API,解决多核多线程的可以自动管理线程的生命周期的强大API。
简单描述下GCD和NSOperation的区别:
- GCD是基于C语言的,并不属于cocoa库
- NSOperation是基于GCD衍生出来的,但他是面向对象的,支持设置线程并发数,线程、任务优先级,依赖关系等。更适用于复杂的业务处理
- GCD相比来说更简单些,只需要执行block块中的代码即可。而NSOperationQueue是对象,所以相比来说更复杂点。
- 所以如果你的业务不是很复杂,那么GCD足够满足你了。代码看起来也会更加整洁。比较推荐的多线程。
dispatch_group
先说一下为什么使用这个,有点类似于队列,其实简单来说就是为了方便管理。打个比方:
比如你有100个孩子,然后你想知道谁快谁慢,如果不管理,他们乱跑,我们并不知道谁快谁慢。所以把他们分好班,排好序是最好的解决办法。
然后因为是并发的,所以到了吃饭的时候,他们有可能都去抢同一个吃的。孩子是天真的,他们只会同时去抢。其实我的资源是够用的,但是因为大家一窝蜂的来,就容易挤爆了。而且这对于饭来说是很不安全的,多个人同时来吃同一份饭,饭就不知道自己该让谁吃,最终crash。
网络请求大部分时候是异步的,用到多线程的大多也都是异步的.
而队列遵循先进先出原则,同时限制了进入的个数,保证线程个数,以及数据唯一性。所以应用场景也大致就明确了。
dispatch_group的使用也很简单,GCD封装的都很简单易懂。只需要了解几个方法即可:
- dispatch_group_enter(group); 任务进去队列
-
dispatch_group_async(group,queue,^{
}); 执行任务代码 - dispatch_group_leave(group);任务完成离开队列
- dispatch_group_wait(group, DISPATCH_TIME_FOREVER);等待上面的任务执行完成,第二个参数为等待时间
-
dispatch_group_notify(group queue, ^{
});所有任务都完成才会调用此方法
具体贴点代码差不多就理解了:
dispatch_group_t groupOne = dispatch_group_create();
dispatch_queue_t queueOne = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//group通常用于异步使用
dispatch_group_enter(groupOne);
dispatch_group_async(groupOne, queueOne, ^{
sleep(5);
dispatch_group_leave(groupOne);
});
//group wait等待线程
dispatch_group_enter(groupOne);
dispatch_group_async(groupOne, queueOne, ^{
dispatch_group_async(groupOne, queueOne, ^{
sleep(8);
NSLog(@"会等待");
});
dispatch_group_leave(groupOne);
});
//wait函数一直阻塞,直到它发现group里面的任务全部leave,它才放弃阻塞(任务全部完成)
dispatch_group_wait(groupOne, DISPATCH_TIME_FOREVER);
//普通异步线程
dispatch_group_enter(groupOne);
dispatch_async(queueOne, ^{
sleep(2);
dispatch_group_leave(groupOne);
});
//group异步先执行完毕线程
dispatch_group_enter(groupOne);
dispatch_group_async(groupOne, queueOne, ^{
dispatch_group_leave(groupOne);
NSLog(@"我先完成");
});
//all结束
dispatch_group_notify(groupOne, queueOne, ^{
NSLog(@"dispatch_group_notify 执行,AllOver");
});
总结:
- dispatch_group的异步和普通线程的异步并无差别,使用方式均一样
- 所有leave执行完毕才会执行结束
- wait函数一直阻塞,直到它发现group里面的任务全部leave,它才放弃阻塞(任务全部完成) 注意用法,使用不对不生效
- enter和leave一定要成对出现,是一定。
- 特殊说明一下子线程可能无法回调delegate,因为子线程被释放了所以无法回调delegate,解决办法就是在子线程中继续执行任务持续占用。但是不推荐,牵扯到delegate的尽量放在主线程操作。