参考了不少博客,部分参考别人,附含一些自己的见解
参考博客:http://www.tuicool.com/articles/ZNn6Jz
1、GCD是我们iOS开发很重要的一些方法,它形式简单,但功能强大,但里面有很多又难以让人理解
比如进程和线程的区别?串行队列,和并行队列的区别?以及同步和异步的区别?get和post的区别?
dispatch_get_global_queue(0,0)和dispatch_get_main_queue(),还有dispatch_queue_create("test",NUll)这三种方法创建队列的区别?
2、GCD是用c语言写的函数,dispatch_queue_create(参数1,参数2);参数1是队列的名称,在调试时会有用,所以尽量不要用重名,第二个参数,我见过的有DISPATCH_QUEUE_SERIAL,这代表生存的队列是串行的,任务在单线程中执行,加载到此队列里面的任务会按先进先出的方式执行。
如果第二个参数是DISPATCH_QUEUE_CONCURRENT那么生存的队列是一个并发队列,里面的任务被分发到多个线程中去执行。
dispatch_get_global_queue(0,0)获得其实是一个并发队列
dispatch_get_main_queue()获得的其实是一个串行队列
为什么说这连个队列都不能用dispatch_resume()和dispatch_suspend()来控制队列的继续还是中断,解释原因是因为这是系统自动生存的。
3、接下来就是加载任务的同步和异步
dispatch_async(queue,^ {
});//异步执行block,函数立即返回
dispatch_sync(queue,^{
//block具体代码
});//同步执行block,函数一直等到block执行完毕才返回。
同步我们在使用中尽量少用,它是必须让queue执行完毕后才能执行里面的东西
4、在测试的过程中我发现这么一个问题
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"同步3");
});//单独写这么一个方法将之方到viewdidload里面执行,发现那句打印语句根本就不执行,但是如果我们将队列换成global或者换成一个新建的队列就执行里面的语句就能执行,我的理解是可能主线程队列还没有结束,必须等到他结束了才执行,而其他队列都不是主线程,相当于在另一个线程中运行。上面那里出现不打印相当于同步死锁一样,这是我的理解。
4、项目中常见的GCD模型
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^ {
//子线程中开始网络请求数据,全局队列执行
dispatch_sync(dispatch_get_main_queue(),^{
//主线程更新UI代码
});
});//注意特征,前一个队列是全局队列,也是一个子线程,或者说后台执行;后一个队列是主线程
5、可以用串行队列实现一个锁的功能,比如多线程写同一个数据库,需要保持写入的顺序和每一个写入的完整性
dispatch_queue_t queue = dispatch_queue_create("com.dispatch.writedb",DISPATCH_QUEUE_SERIAL);//这是一个串行队列
- (void)writeDB:(NSData *data) {
dispatch_sync(queue,^{
)};//同步必须等queue执行完毕再说
6、一些特别的dispatch方法
一次性执行
static dispatch_once_t onceToken;
dispatch_once(&onceToken,^{
//代码执行的地方
});//这个在我们建单例的时候用到它。
延时执行
double delayInSeconds = 2.0;
dispatch_time_t poptime = dispatch_time (DISPATCH_TIME_NOW,delayInSeconds *NSEC_PER_SEC);
dispatch_after(portime,dispatch_get_main_queue(),^(void) {
//执行代码的地方
});
高级用法:让后台连个线程并行执行,然后等两个线程都结束后,再汇总执行结果,代码如下
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group,dispatch_get_global_queue(0,0),^{
//并行执行的线程一
});
dispatch_group_async(group,dispatch_get_global_queue(0,0),^{
//并行执行的线程二
});
dispatch_group_notify(group,dispatch_get_global_queue(0,0),^{
//合并结果
});//这个可以用在加载大型图片,太偏太大,如果我们仅仅开一个线程速度可能会慢,我们可以跟后台协商,将一张图片划分为几张图片,然后,分几个线程去下载,然后下载完成后,在合并图片(就是将一部分准确的放到屏幕上去)