GCD
2017-11-22 本文已影响1人
6灰太狼9
Grand Central Dispatch (GCD),是苹果推出的多线程解决方案,它主要用于优化应用程序以支持多核处理器以及其他对称多处理系统。
GCD作用
1.GCD可用于多核的并发运算
2.GCD会自动利用更多的CPU内核
3.GCD会自动管理线程的生命周期(创建线程、调度任务、销毁线程)
GCD执行
GCD的使用步骤比较简单。1.创建一个队列(串行队列或并行队列)2.将任务添加到队列中,然后系统就会根据任务类型执行任务(同步执行或异步执行)
这里我们又看到两个GCD的核心概念:任务和队列
任务在GCD中其实就是Block中的代码块,对任务的执行方式有同步执行(在当前线程中执行任务,不需要开启新的线程)和异步执行(需要开启新的线程,然后在新线程中执行任务)
//同步执行任务 在某个队列中
dispatch_sync(queue, ^{
//任务代码
});
//异步执行任务 在某个队列中
dispatch_async(queue, ^{
//任务代码
});
队列可以分为串行队列(让任务一个接一个的执行)和并行队列(可以<不是一定>让多个任务并发执行,即开启多个线程同时执行任务)
dispatch_queue_t queue1 = dispatch_queue_create("test", DISPATCH_QUEUE_SERIAL); //创建串行队列
dispatch_queue_t queue2 = dispatch_queue_create("test", DISPATCH_QUEUE_CONCURRENT); //创建并行队列
dispatch_queue_t queue3 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);//获取全局并发队列
dispatch_queue_t queue = dispatch_get_main_queue();//获取主队列 这个队列比较特殊
所以队列和任务有六种组合方式
并行队列 | 串行队列 | 主队列 | |
---|---|---|---|
同步(sync) | 没有开启新的线程,串行执行任务 | 没有开启新的任务,串行执行任务 | 卡主 |
异步(async) | 开启新的线程,并行执行任务 | 开启一个新的线程,串行执行 | 没有开启新的任务,串行执行任务 |
//主队列同步执行 会卡住 main_sync中的整个代码相当于主线程中一个任务S,
执行到A又会给主线程中添加一个同步任务A, 因为是同步执行,任务A在等任务S执行完才能执行,
但任务S执行完必须是任务A完成后直接往下执行B和任务C才算完成,这就互相等待了。
- (void)main_sync{ //S
dispatch_queue_t queue = dispatch_get_main_queue();
NSLog(@"begin");
dispatch_sync(queue, ^{ //A
for (int i=0; i<2; i++) {
NSLog(@"1-----%@",[NSThread currentThread]);
}
});
dispatch_sync(queue, ^{//B
for (int i=0; i<2; i++) {
NSLog(@"2-----%@",[NSThread currentThread]);
}
});
dispatch_sync(queue, ^{//C
for (int i=0; i<2; i++) {
NSLog(@"3-----%@",[NSThread currentThread]);
}
});
NSLog(@"end");
}
看的出来开没有开启新线程和队列的性质没有关系,主要看执行任务的方式。
GCD常见用法
延时执行
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// 2秒后异步执行这里的代码...
NSLog(@"run-----");
});
使用dispatch_once函数能保证某段代码在程序运行过程中只被执行1次。
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// 只执行1次的代码(这里面默认是线程安全的)
});
执行完队列组中所有的 耗时操作后 通过dispatch_group_notify 回到主线程。
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 执行1个耗时的异步操作
});
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 执行1个耗时的异步操作
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// 等前面的异步操作都执行完毕后,回到主线程...
});