首先说一下四个概念
异步执行:开启一个子线程执行代码,不会堵塞主线程,
同步执行:只有执行完代码,才会执行下面的代码,会堵塞主线程
并行队列:运行多个子线程同时存在和运行
串行队列:最多只准一个子线程存在和运行
1.异步执行 + 并行队列
- (void)oneClick{
//创建一个并行队列
dispatch_queue_t queue = dispatch_queue_create("标识符", DISPATCH_QUEUE_CONCURRENT);
NSLog(@"---start---");
//使用异步函数封装三个任务
dispatch_async(queue, ^{
NSLog(@"任务1---%@", [NSThread currentThread]);
dispatch_async(queue, ^{
NSLog(@"任务2---%@", [NSThread currentThread]);
dispatch_async(queue, ^{
NSLog(@"任务3---%@", [NSThread currentThread]);
NSLog(@"---end---");
}
执行结果如下
2017-12-20 14:36:19.352878+0800 BmobTest[2072:107235] ---start---
2017-12-20 14:36:19.353207+0800 BmobTest[2072:107235] ---end---
2017-12-20 14:36:19.353356+0800 BmobTest[2072:110787] 任务1---<NSThread: 0x604000274e00>{number = 10, name = (null)}
2017-12-20 14:36:19.353401+0800 BmobTest[2072:115296] 任务2---<NSThread: 0x604000274880>{number = 12, name = (null)}
2017-12-20 14:36:19.353419+0800 BmobTest[2072:115304] 任务3---<NSThread: 0x60000026b000>{number = 11, name = (null)}
可以看出,不在dispatch_async里的两个NSLog,他们会在自己执行完,才会继续执行下面的代码,也就是说代码默认同步执行。然后通过dispatch_async可以开启子线程去执行代码,因为队列之前设置为了DISPATCH_QUEUE_CONCURRENT(并行队列),使得多个子线程可以同时进行。
记得看{number = 10, name = (null)} 这个描述,number说的是子线程的号码,name为空一般都指的是子线程,如果为main指的是主线程。
2.异步执行 + 串行队列
- (void)twoClick{
//创建一个串行队列
dispatch_queue_t queue = dispatch_queue_create("标识符", DISPATCH_QUEUE_SERIAL);
NSLog(@"---start---");
//使用异步函数封装三个任务
dispatch_async(queue, ^{
NSLog(@"任务1---%@", [NSThread currentThread]);
dispatch_async(queue, ^{
NSLog(@"任务2---%@", [NSThread currentThread]);
dispatch_async(queue, ^{
NSLog(@"任务3---%@", [NSThread currentThread]);
NSLog(@"---end---");
}
结果如下
2017-12-20 14:42:02.193245+0800 BmobTest[2072:107235] ---start---
2017-12-20 14:42:02.193708+0800 BmobTest[2072:107235] ---end---
2017-12-20 14:42:02.193789+0800 BmobTest[2072:116957] 任务1---<NSThread: 0x604000273b80>{number = 13, name = (null)}
2017-12-20 14:42:02.194039+0800 BmobTest[2072:116957] 任务2---<NSThread: 0x604000273b80>{number = 13, name = (null)}
2017-12-20 14:42:02.194436+0800 BmobTest[2072:116957] 任务3---<NSThread: 0x604000273b80>{number = 13, name = (null)}
可以看到线程的号码都是13,name为空,说明都是用的一个子线程。为什么?因为队列类型设置为串行,我们最多只能运行一个子线程。如果之前开启了一个子线程,下面又想开启一个子线程,这个时候他就开不出来,只能等上一个子线程执行完代码,然后再去使用这个线程。因为执行的都在子线程,所以还是没有普通的NSLog执行的快,毕竟开启线程也需要时间。
3.同步执行 + 并行队列
- (void)threeClick{
//创建一个并行队列
dispatch_queue_t queue = dispatch_queue_create("标识符", DISPATCH_QUEUE_CONCURRENT);
NSLog(@"---start---");
//使用同步函数封装三个任务
dispatch_sync(queue, ^{
NSLog(@"任务1---%@", [NSThread currentThread]);
dispatch_sync(queue, ^{
NSLog(@"任务2---%@", [NSThread currentThread]);
dispatch_sync(queue, ^{
NSLog(@"任务3---%@", [NSThread currentThread]);
NSLog(@"---end---");
}
结果
2017-12-20 14:46:36.583972+0800 BmobTest[2072:107235] ---start---
2017-12-20 14:46:36.584407+0800 BmobTest[2072:107235] 任务1---<NSThread: 0x604000063840>{number = 1, name = main}
2017-12-20 14:46:36.584633+0800 BmobTest[2072:107235] 任务2---<NSThread: 0x604000063840>{number = 1, name = main}
2017-12-20 14:46:36.584841+0800 BmobTest[2072:107235] 任务3---<NSThread: 0x604000063840>{number = 1, name = main}
2017-12-20 14:46:36.584966+0800 BmobTest[2072:107235] —end---
首先注意dispatch_sync这个函数,指的是同步,额,也就是说我们当他不存在也是可以的。所以这个执行结果就很正常。队列类型为并行,额,因为没有开启子线程,这个东西也是摆设。
4.同步执行 + 串行队列
- (void)fourClick{
//创建一个串行队列
dispatch_queue_t queue = dispatch_queue_create("标识符", DISPATCH_QUEUE_SERIAL);
NSLog(@"---start---");
//使用异步函数封装三个任务
dispatch_sync(queue, ^{
NSLog(@"任务1---%@", [NSThread currentThread]);
dispatch_sync(queue, ^{
NSLog(@"任务2---%@", [NSThread currentThread]);
dispatch_sync(queue, ^{
NSLog(@"任务3---%@", [NSThread currentThread]);
NSLog(@"---end---");
}
结果
2017-12-20 14:50:53.478014+0800 BmobTest[2072:107235] ---start---
2017-12-20 14:50:53.478444+0800 BmobTest[2072:107235] 任务1---<NSThread: 0x604000063840>{number = 1, name = main}
2017-12-20 14:50:53.478585+0800 BmobTest[2072:107235] 任务2---<NSThread: 0x604000063840>{number = 1, name = main}
2017-12-20 14:50:53.478969+0800 BmobTest[2072:107235] 任务3---<NSThread: 0x604000063840>{number = 1, name = main}
2017-12-20 14:50:53.479445+0800 BmobTest[2072:107235] —end---
这个和之前的一样,因为是同步没有子线程,队列类型也没用,结果很正常。
5.小结
想要弄清楚GCD就要对这个四个概念很熟悉,无非就是开不开启子线程,运行一个或更多子线程存在和运行,这个两个区别。