GCD 第一节
1.GCD的优势
(1)GCD是苹果公司为多核的并行运算提出的解决方案;
(2)GCD会自动利用更多的CPU内核(比如双核、四核);
(3)GCD会自动管理线程的生命周期(创建线程、调度任务、销毁线程;
(4)程序员只需要告诉GCD想要执行什么任务,不需要编写任何线程管理代码;
2 GCD依赖的库 libdispatch.dylib,每次新建工程的时候,已经自动加载了,无需我们手动添加
3.GCD有2个核心概念
(1)任务:执行的操作;
(2)队列:用来存放任务;
使用步骤:定制任务 —— 确定想做的事情;
将任务添加到队列中,GCD会自动将队列中的任务取出,放到对应的线程中执行;
任务的取出遵循队列的FIFO原则:先进先出,后进后出;
4.GCD中有2个执行任务的函数:
(1)用同步的方式执行任务 dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
(2)用异步的方式执行务 dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
queue:队列 block:任务;把任务放到队列中进行执行;
5. 队列
(1)并发队列(Concurrent Dispatch Queue)
可以让多个任务并发执行(自动开启多个线程同时执行任务)并发功能执行在异步函数下才有效;
(2)串行队列 (Serial Dispatch Queue)让任务一个接一个的执行;
(3) 队列的创建方法
1. 使用dispatch_queue_create函数创建串行队列
dispatch_queue_t queue = dispatch_queue_create(<#const char *label#>, <#dispatch_queue_attr_t attr#>)
参数一:
指定队列的名称,Dispatch Queue 的名称推荐使用应用程序ID,该名称在Xcode和Instruments的调试器中作为Dispatch Queue 的名称表示,同时这 个名称也会出现在应用程序崩溃时所产生的CrashLog中。方便我们进行查找。
参数二:
当创建串行队列的时候定义为NULL就可以了,当创建并发队列的时候定义为DISPATCH_QUEUE_CONCURRENT
dispatch_queue_t queue =dispatch_queue_create("test19",DISPATCH_QUEUE_CONCURRENT);
dispatch_queue_t queue =dispatch_queue_create("test18",NULL);
注意:
在对iOS6.0以下的版本,我们需要使用dispatch_release(这里是queue的名称)
对于iOS6.0以上的版本,就不需要使用了
http://blog.csdn.net/yohunl/article/details/17301875
2 使用dispatch_get_global_queue函数获得全局的并发队列 这个是获取的,不需要手动的创建
dispatch_queue_t queue = dispatch_get_global_queue(long identifier, <#unsigned long flags#>)
参数一:
long identifier:ios 8.0 告诉队列执行任务的“服务质量 quality of service”,系统提供的参数有:
#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
参数二:
unsigned long flags:苹果官方文档是这样解释的: Flags that are reserved for future use。标记是为了未来使用保留的!所以这个参数应该永远指定为0
如果做ios8.0与ios7.0的适配,可以这样创建全局队列:
dispatch_queue_t q = dispatch_get_global_queue(0, 0);
试着用全局队列来做一下异步操作,看看是否为并发执行,如下代码
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); //获得全局并发队列
3.使用主队列(跟主线程相关联的队列)主队列是GCD自带的一种特殊的串行队列,放在主队列中的任务,都会放到主线程中执行
使用dispatch_get_main_queue()获得主队列
dispatch_queue_t queue = dispatch_get_main_queue();
注意:
同步:在当前线程中执行任务,不具备开启新线程的能力;
异步:在新的线程中执行任务,具备开启新线程的能力;
并发:多个任务并发(同时)执行;
串行:一个任务执行完毕后,再执行下一个任务;
6.并发串行队列和同步异步函数组合的结果
同步函数不具备开启线程的能力,无论是什么队列都不会开启线程;
异步函数具备开启线程的能力,开启几条线程由队列决定(串行队列只会开启一条新的线程,并发队列会开启多条线程)。
1,全局并发队列加入到了异步函数中,开启了新的线程,并发执行
- (void)test1{
dispatch_queue_t queue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
dispatch_async(queue, ^{
NSLog(@"下载1------%@",[NSThreadcurrentThread]);
});
dispatch_async(queue, ^{
NSLog(@"下载2------%@",[NSThreadcurrentThread]);
});
dispatch_async(queue, ^{
NSLog(@"下载3------%@",[NSThreadcurrentThread]);
});
NSLog(@"主线程----%@",[NSThreadmainThread]);
// 2016-03-06 23:09:07.831 GCDDemo[1338:19177]下载2------<NSThread: 0x7f9550f1af00>{number = 3, name = (null)}
// 2016-03-06 23:09:07.831 GCDDemo[1338:19176]下载1------<NSThread: 0x7f9550d84100>{number = 2, name = (null)}
// 2016-03-06 23:09:07.831 GCDDemo[1338:19178]下载3------<NSThread: 0x7f9550e23720>{number = 4, name = (null)}
// 2016-03-06 23:09:07.831 GCDDemo[1338:19054]主线程----<NSThread: 0x7f9550f041c0>{number = 1, name = main}
}
- (void)test12{
dispatch_queue_t queue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
dispatch_sync(queue, ^{
NSLog(@"下载1------%@",[NSThreadcurrentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"下载2------%@",[NSThreadcurrentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"下载3------%@",[NSThreadcurrentThread]);
});
NSLog(@"主线程----%@",[NSThreadmainThread]);
// 2016-03-06 23:15:36.613 GCDDemo[1522:22205] 下载1------<NSThread: 0x7fd6b1509660>{number = 1, name = main}
// 2016-03-06 23:15:36.613 GCDDemo[1522:22205] 下载2------<NSThread: 0x7fd6b1509660>{number = 1, name = main}
// 2016-03-06 23:15:36.614 GCDDemo[1522:22205] 下载3------<NSThread: 0x7fd6b1509660>{number = 1, name = main}
// 2016-03-06 23:15:36.614 GCDDemo[1522:22205] 主线程----<NSThread: 0x7fd6b1509660>{number = 1, name = main}
}
2.全局并发队列 放到同步函数中没有开启新的线程,串行执行
- (void)test12{
dispatch_queue_t queue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
dispatch_sync(queue, ^{
NSLog(@"下载1------%@",[NSThreadcurrentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"下载2------%@",[NSThreadcurrentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"下载3------%@",[NSThreadcurrentThread]);
});
NSLog(@"主线程----%@",[NSThreadmainThread]);
// 2016-03-06 23:15:36.613 GCDDemo[1522:22205] 下载1------<NSThread: 0x7fd6b1509660>{number = 1, name = main}
// 2016-03-06 23:15:36.613 GCDDemo[1522:22205] 下载2------<NSThread: 0x7fd6b1509660>{number = 1, name = main}
// 2016-03-06 23:15:36.614 GCDDemo[1522:22205] 下载3------<NSThread: 0x7fd6b1509660>{number = 1, name = main}
// 2016-03-06 23:15:36.614 GCDDemo[1522:22205] 主线程----<NSThread: 0x7fd6b1509660>{number = 1, name = main}
}
3.串行队列在异步函数中 会开启一个线程串行的执行;
- (void)test13{
dispatch_queue_t queue =dispatch_queue_create("queue1",NULL);
dispatch_async(queue, ^{
NSLog(@"异步函数往串行队列中1----%@",[NSThreadcurrentThread]);
});
dispatch_async(queue, ^{
NSLog(@"异步函数往串行队列中2----%@",[NSThreadcurrentThread]);
});
dispatch_async(queue, ^{
NSLog(@"异步函数往串行队列中3----%@",[NSThreadcurrentThread]);
});
/*
2016-03-07 22:15:55.689 GCDDemo[1138:18345] 异步函数往串行队列中1----<NSThread: 0x7f88214b1670>{number = 2, name = (null)}
2016-03-07 22:15:55.689 GCDDemo[1138:18345] 异步函数往串行队列中2----<NSThread: 0x7f88214b1670>{number = 2, name = (null)}
2016-03-07 22:15:55.690 GCDDemo[1138:18345] 异步函数往串行队列中3----<NSThread: 0x7f88214b1670>{number = 2, name = (null)}
*/
}
4.串行队列放入到同步函数中会串行执行,不开启新的线程
-(void)test14{
dispatch_queue_t queue =dispatch_queue_create("patch1",NULL);
dispatch_sync(queue, ^{
NSLog(@"同步函数往串行队列1---%@",[NSThreadcurrentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"同步函数往串行队列2---%@",[NSThreadcurrentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"同步函数往串行队列3---%@",[NSThreadcurrentThread]);
});
/*
2016-03-07 22:21:33.219 GCDDemo[1293:20615] 同步函数往串行队列1---<NSThread: 0x7fa3e140ad20>{number = 1, name = main}
2016-03-07 22:21:33.220 GCDDemo[1293:20615] 同步函数往串行队列2---<NSThread: 0x7fa3e140ad20>{number = 1, name = main}
2016-03-07 22:21:33.220 GCDDemo[1293:20615] 同步函数往串行队列3---<NSThread: 0x7fa3e140ad20>{number = 1, name = main}
*/
}
5.主线程同步执行,会阻塞线程
-(void)test15{
//这种方法阻塞了主线程
dispatch_queue_t queue =dispatch_get_main_queue();
dispatch_sync(queue, ^{
NSLog(@"主队列--1%@",[NSThreadcurrentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"主队列--2%@",[NSThreadcurrentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"主队列--3%@",[NSThreadcurrentThread]);
});
NSLog(@"主队列--0%@",[NSThreadcurrentThread]);
}
6.主线程在异步函数中,不会开启新的线程,串行的执行;
-(void)test16{
//这种方法阻塞了主线程
dispatch_queue_t queue =dispatch_get_main_queue();
dispatch_async(queue, ^{
NSLog(@"主队列--1%@",[NSThreadcurrentThread]);
});
dispatch_async(queue, ^{
NSLog(@"主队列--2%@",[NSThreadcurrentThread]);
});
dispatch_async(queue, ^{
NSLog(@"主队列--3%@",[NSThreadcurrentThread]);
});
NSLog(@"主队列--0%@",[NSThreadcurrentThread]);
/*
2016-03-08 10:47:33.020 GCDDemo[1965:36074] 主队列--0<NSThread: 0x7f9b50f032c0>{number = 1, name = main}
2016-03-08 10:47:33.025 GCDDemo[1965:36074] 主队列--1<NSThread: 0x7f9b50f032c0>{number = 1, name = main}
2016-03-08 10:47:33.025 GCDDemo[1965:36074] 主队列--2<NSThread: 0x7f9b50f032c0>{number = 1, name = main}
2016-03-08 10:47:33.026 GCDDemo[1965:36074] 主队列--3<NSThread: 0x7f9b50f032c0>{number = 1, name = main}
*/
}
-(void)test18{
dispatch_queue_t queue =dispatch_queue_create("test18",NULL);
dispatch_async(queue, ^{
NSLog(@"test18---1---%@",[NSThreadcurrentThread]);
});
dispatch_async(queue, ^{
NSLog(@"test18---2---%@",[NSThreadcurrentThread]);
});
dispatch_async(queue, ^{
NSLog(@"test18---3---%@",[NSThreadcurrentThread]);
});
/*
2016-03-14 11:45:04.858 GCDDemo[6083:100657] test18---1---<NSThread: 0x7f9ea052be30>{number = 2, name = (null)}
2016-03-14 11:45:04.859 GCDDemo[6083:100657] test18---2---<NSThread: 0x7f9ea052be30>{number = 2, name = (null)}
2016-03-14 11:45:04.860 GCDDemo[6083:100657] test18---3---<NSThread: 0x7f9ea052be30>{number = 2, name = (null)}
*/
}
- (void)test19{
dispatch_queue_t queue =dispatch_queue_create("test19",DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSLog(@"test19---1---%@",[NSThreadcurrentThread]);
});
dispatch_async(queue, ^{
NSLog(@"test19---2---%@",[NSThreadcurrentThread]);
});
dispatch_async(queue, ^{
NSLog(@"test19---3---%@",[NSThreadcurrentThread]);
});
/*
2016-03-14 11:45:04.858 GCDDemo[6083:100659] test19---2---<NSThread: 0x7f9ea070bf00>{number = 3, name = (null)}
2016-03-14 11:45:04.858 GCDDemo[6083:100658] test19---1---<NSThread: 0x7f9ea0509560>{number = 4, name = (null)}
2016-03-14 11:45:04.858 GCDDemo[6083:100689] test19---3---<NSThread: 0x7f9ea0709f80>{number = 5, name = (null)}
*/
}