1.
什么是
GCD
全称
Grand Central Dispatch
,可译为
“
中枢调度器
”,
纯C语言,提供了非常多强大的函数
优点:
GCD
会自动管理线程的生命周期(创建线程,调度任务,销毁线程),
自动利用更多的CPU内核(比如双核,四核)
GCD的任务的取出遵循队列的
FIFO
原则:先进先出,后进后出
容易混淆的术语
1>.
同步和异步主要影响:能不能开启新的线程
同步:在当前线程中执行任务,不具备开启新线程的能力
异步:在新的线程中执行任务,具备开启新线程的能力
2>.
并发和串行主要影响:任务的执行方式
并发:多个任务并发(同时)执行
并发:多个任务并发(同时)执行
串行:一个任务执行完毕后,再执行下一个任务
GCD
中有
2
个用来执行任务的函数
2.执行的任务:
1>.
用同步的方式执行任务
void dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
queue: 队列
block:任务
2>. 用异步的方式执行任务
void dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
queue: 队列
block:任务
2>. 用异步的方式执行任务
void dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
队列的类型
GCD 的队列可以分为 2 大类型
并发队列(Concurrent Dispatch Queue)
可以让多个任务并发(同时)执行(自动开启多个线程同时执行任务)
GCD 的队列可以分为 2 大类型
并发队列(Concurrent Dispatch Queue)
可以让多个任务并发(同时)执行(自动开启多个线程同时执行任务)
并发功能只有在异步(dispatch_async)函数下才有效
串行队列(Serial Dispatch Queue)
让任务一个接着一个地执行(一个任务执行完毕后,再执行下一个任务)
让任务一个接着一个地执行(一个任务执行完毕后,再执行下一个任务)
并发队列 /**** 重要 *****/
GCD
默认已经提供了全局的并发队列,供整个应用使用,不需要手动创建
使用
dispatch_queue_t dispatch_get_global_queue(long identifier, unsigned long flags);
返回值 dispatch_queue_t 队列
参数 long identifier 全局并发队列优先级
使用
dispatch_queue_t dispatch_get_global_queue(long identifier, unsigned long flags);
返回值 dispatch_queue_t 队列
参数 long identifier 全局并发队列优先级
参数 unsigned long flags=0 此参数暂时无用,用0即可
//
全局并发队列的优先级
#define DISPATCH_QUEUE_PRIORITY_HIGH 2 高
#define DISPATCH_QUEUE_PRIORITY_DEFAULT 0 默认(中)
#define DISPATCH_QUEUE_PRIORITY_LOW (-2) 低
#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 后台
线程间的使用:
//异步并发执行:
3. GCD 延迟执行
例如:
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
NSLog(@"----touchesBegan");
#if 0
//错误的做法 缺点:卡住当前线程
[NSThread sleepForTimeInterval:3];
NSLog(@"---下载图片");
NSLog(@"----downloadfinished");
#endif
{
NSLog(@"----touchesBegan");
#if 0
//错误的做法 缺点:卡住当前线程
[NSThread sleepForTimeInterval:3];
NSLog(@"---下载图片");
NSLog(@"----downloadfinished");
#endif
#if 0
2>
1.
调用
NSObject
的方法
//一旦定制好 延迟任务后 不会卡住当前线程, 3秒后回到主线程中执行download方法不会卡住当前线程
[self performSelector:@selector(download) withObject:nil afterDelay:3.0f];
NSLog(@"----downloadfinished");
#endif
NSLog(@"----downloadfinished");
#endif
#if 0
//3秒后回到主线程中执行block中的代码,不会造成卡顿
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), queue, ^{
NSLog(@"----下载图片 %@",[NSThread currentThread]);
});
NSLog(@"----downloadfinished");
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), queue, ^{
NSLog(@"----下载图片 %@",[NSThread currentThread]);
});
NSLog(@"----downloadfinished");
#endif
//3
秒后在新建的子线程中执行block中的代码,
不会造成卡顿
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), queue, ^{
NSLog(@"----下载图片 %@",[NSThread currentThread]);
});
NSLog(@"----downloadfinished");
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), queue, ^{
NSLog(@"----下载图片 %@",[NSThread currentThread]);
});
NSLog(@"----downloadfinished");
}
- (void)download
{
NSLog(@"---下载图片 %@",[NSThread currentThread]);
{
NSLog(@"---下载图片 %@",[NSThread currentThread]);
}
4.
一次性代码
- (void)download
{
//一次性代码 使用dispatch_once_t函数能保证某段代码在程序运行过程中只被执行1次(block中的代码默认是线程安全的)
//永远只执行一次,从函数的开始到结束
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSLog(@"下载图片" );
});
// if (self.hasExcuted) return;
// NSLog(@" 下载图片 ");
// self.hasExcuted = YES;
{
//一次性代码 使用dispatch_once_t函数能保证某段代码在程序运行过程中只被执行1次(block中的代码默认是线程安全的)
//永远只执行一次,从函数的开始到结束
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSLog(@"下载图片" );
});
// if (self.hasExcuted) return;
// NSLog(@" 下载图片 ");
// self.hasExcuted = YES;
}
五: GCD 队列组:
1.队列组可以解决如下需求
首先:分别异步执行2个耗时操作
其次:等2个异步操作都执行完毕后,再回到主线程执行操作
//1.
队列组
dispatch_group_t group = dispatch_group_create();
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_async(<#dispatch_group_t group#>, <#dispatch_queue_t queue#>, ^{
//下载图片等操作
});
//(保证组里面所有的任务都执行完成后 再执行notify函数里面的block)
dispatch_group_notify(<#dispatch_group_t group#>, <#dispatch_queue_t queue#>, ^{
//执行图片合并等操作
……..
//回到主线程显示
dispatch_async(dispatch_get_main_queue(), ^{
//显示内容等操作
});
});
//下载图片等操作
});
//(保证组里面所有的任务都执行完成后 再执行notify函数里面的block)
dispatch_group_notify(<#dispatch_group_t group#>, <#dispatch_queue_t queue#>, ^{
//执行图片合并等操作
……..
//回到主线程显示
dispatch_async(dispatch_get_main_queue(), ^{
//显示内容等操作
});
});
要求:
//例如:
//1
分别下载两张图片:大图片
logo
//2 合并两张图片
//3 显示到一个 imageView 上
// 百度 logo http://img.baidu.com/img/baike/logo-baike.png
//2 合并两张图片
//3 显示到一个 imageView 上
// 百度 logo http://img.baidu.com/img/baike/logo-baike.png
此处还可以用异步并发队列来实现此功能