##什么是GCD:
1、GCD是苹果开发的一个多核编程的解决方法,和其它多线程技术方案相比,使用起来更加简单和方便.
2、纯C语言,提供了非常多强大的函数
## GCD的优势:
1、GCD是苹果公司为多核的并行运算提出的解决方案
2、GCD会自动利用更多的CPU内核(比如双核、四核)
3、GCD会自动管理线程的生命周期(创建线程、调度任务、销毁线程)
4、程序员只需要告诉GCD想要执行什么任务,不需要编写任何线程管理代码
##队列和任务:
GCD中有2个核心概念
任务:执行什么操作,用block来封装任务。
队列:用来存放任务。
将任务添加到队列中GCD会自动将队列中的任务取出,放到对应的线程中执行。
任务的取出遵循队列的FIFO原则:先进先出,后进后出 。
队列的类型
并发队列:可以让多个任务并发(同时)执行(自动开启多个线程同时执行任务),并发功能只有在异步(dispatch_async)函数下才有效。
1、获得全局的并发队列
~~~
//dispatch_queue_priority_t priority:队列的优先级
//unsigned long flags:此参数暂时无用,用0即可
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
~~~
全局并发队列的优先级
~~~
#define DISPATCH_QUEUE_PRIORITY_HIGH 2 // 高
#define DISPATCH_QUEUE_PRIORITY_DEFAULT 0 // 默认(中)
#define DISPATCH_QUEUE_PRIORITY_LOW (-2) // 低
#define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN// 后台
~~~
串行队列:让任务一个接着一个地执行(一个任务执行完毕后,再执行下一个任务)。
1、使用dispatch_queue_create函数创建串行队列
~~~
//const char *label:队列名称
//dispatch_queue_attr_t attr:队列属性,一般用NULL即可
dispatch_queue_t queue = dispatch_queue_create("cn.XXX",NULL);
~~~
~~~
dispatch_release(queue); // 非ARC需要释放手动创建的队列
~~~
2、使用主队列(跟主线程相关联的队列),主队列是GCD自带的一种特殊的串行队列
放在主队列中的任务,都会放到主线程中执行
使用dispatch_get_main_queue()获得主队列
~~~
dispatch_queue_t queue = dispatch_get_main_queue();
~~~
执行任务:
1、用同步的方式执行任务
~~~
dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
~~~
2、用异步的方式执行任务
~~~
dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
~~~
同步和异步的区别:
1、同步:只能在当前线程中执行任务,不具备开启新线程的能力。dispatch_sync
2、异步:可以在新的线程中执行任务,具备开启新线程的能力。 dispatch_async
队列和执行任务方式组合分析:
ps 特别注意:使用sync函数往当前串行队列中添加任务,会卡住当前的串行队列
![](https://box.kancloud.cn/2016-03-07_56dd401028c5b.jpg)
~~~
/**
* 异步全局并发
* async并发队列(最常用)
* 会创建线程,一般同时开多条
* 并发执行
**/
-(void)asyncGlobalQueue{
//获取全局并发队列
//dispatch_queue_priority_t priority:队列的优先级
//unsigned long flags:此参数暂时无用,用0即可
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//将任务添加到全局队列中去异步执行
dispatch_async(queue, ^{
NSLog(@"------下载图片1----%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下载图片2-----%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"----下载图片3------%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下载图片4----%@",[NSThread currentThread]);
});
}
/**
* 串行队列(有时候会用)
* 会创建线程,一般只开一条
* 串行执行,(一个任务执行完毕后再执行下一个任务)
**/
-(void)asyncSerialQueue{
//创建串行队列
//const char *label:队列名称
//dispatch_queue_attr_t attr:队列属性,一般用NULL即可
dispatch_queue_t queue = dispatch_queue_create("cn.XXX",NULL);
//将任务添加到串行队列中 异步执行
dispatch_async(queue,^{
NSLog(@"--------下载图片1---------%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"--------下载图片2---------%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"--------下载图片3---------%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"--------下载图片4---------%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"--------下载图片5---------%@",[NSThread currentThread]);
});
}
/**
* async --主队列(很常用)
**/
-(void)asyncMainQueue{
//主队列(添加到主队列中的任务,都会自动放到主线程中去执行)
dispatch_queue_t queue = dispatch_get_main_queue();
//添加任务到主队列中异步执行
dispatch_async(queue, ^{
NSLog(@"--------下载图片1---------%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"--------下载图片2---------%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"--------下载图片3---------%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"--------下载图片4---------%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"--------下载图片5---------%@",[NSThread currentThread]);
});
}
/**
* sync --主队列(不能用,会卡死)
**/
-(void)syncMainQueue{
//主队列(添加到主队列中的任务,都会自动放到线程中去执行)
dispatch_queue_t queue = dispatch_get_main_queue();
//将任务添加到主队列中同步执行
dispatch_sync(queue, ^{
NSLog(@"--------下载图片1---------%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"--------下载图片2---------%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"--------下载图片3---------%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"--------下载图片4---------%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"--------下载图片5---------%@",[NSThread currentThread]);
});
}
/**
* sync --并发队列
* 不会创建线程
* 串行执行(一个任务执行完毕后再执行下一个任务)
* 并发队列失去了并发的功能
**/
-(void)syncGlobalQueue{
//获取全局的并发队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//将任务添加到全局并发队列中同步执行
dispatch_sync(queue, ^{
NSLog(@"--------下载图片1---------%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"--------下载图片2---------%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"--------下载图片3---------%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"--------下载图片4---------%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"--------下载图片5---------%@",[NSThread currentThread]);
});
}
/**
* sync --串行队列
* 不会创建线程
* 串行执行(一个任务执行完毕后再执行下一个任务)
**/
-(void)syncSerialQueue{
//创建一个串行队列
dispatch_queue_t queue = dispatch_queue_create("cn.xxx", NULL);
//将任务添加到串行队列中同步执行
dispatch_sync(queue, ^{
NSLog(@"--------下载图片1---------%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"--------下载图片2---------%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"--------下载图片3---------%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"--------下载图片4---------%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"--------下载图片5---------%@",[NSThread currentThread]);
});
}
~~~
一次性执行:
~~~
//一次性执行
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//<#code to be executed once#>
});
~~~
延时执行:
~~~
//延时执行(2秒)
double delayInSeconds = 2;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// <#code to be executed after a specified delay#>
});
~~~
线程组:后台并发执行线程,等所有线程执行结束后再汇总执行结果
~~~
//1、获取线程组
dispatch_group_t group = dispatch_group_create();
//2、并行执行线程
dispatch_group_async(group, queue, ^{
//并发执行线程一
);
ispatch_group_async(group, queue, ^{
//并发执行线程二
});
//3、所有线程执行完成后调用
dispatch_group_notify(group, queue, ^{
//汇总结果
});
~~~
## 线程间通信
从子线程回到主线程
~~~
dispatch_async(
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 执行耗时的异步操作...
dispatch_async(dispatch_get_main_queue(), ^{
// 回到主线程,执行UI刷新操作
});
});
~~~
例子:子线程下载图片,下载后更新界面的imageView.
~~~
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
//子线程下载图片
NSURL *url = [NSURL URLWithString:@"http://d.hiphotos.baidu.com/image/pic/item/37d3d539b6003af3290eaf5d362ac65c1038b652.jpg"];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data];
//回到主线程
dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_async(mainQueue, ^{
self.imageView.image = image;
});
});
}
~~~
- 前言
- iOS开发实践之SQLite3
- iOS开发实践之FMDB
- Obj-C与javascript交互之WebViewJavascriptBridge
- iOS开发实践之UIWebView
- iOS开发实践之多线程(基本概念)
- iOS开发实践之多线程(NSThread)
- iOS开发实践之多线程(GCD)
- iOS开发实践之多线程(单例模式)
- iOS开发实践之xib加载注意问题
- iOS开发实践之多线程(NSOperation)
- iOS开发实践之cell下载图片(NSOperation)
- iOS开发实践之cell下载图片(自定义NSOperation)
- iOS开发实践之cell下载图片(SDWebImage)
- iOS开发实践之JSON
- iOS开发实践之XML
- iOS开发实践之GET和POST请求
- iOS开发实践之网络检测Reachability
- iOS开发实践之MD5加密