相关文章推荐
跑龙套的松树  ·  tf.keras.callbacks.Mod ...·  7 月前    · 
仗义的羽毛球  ·  PolarDBPostgreSQL版PL/S ...·  9 月前    · 
冷冷的马铃薯  ·  LSF作业调度系统 — ...·  1 年前    · 


首先说一下四个概念

异步执行:开启一个子线程执行代码,不会堵塞主线程,
同步执行:只有执行完代码,才会执行下面的代码,会堵塞主线程

并行队列:运行多个子线程同时存在和运行
串行队列:最多只准一个子线程存在和运行

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就要对这个四个概念很熟悉,无非就是开不开启子线程,运行一个或更多子线程存在和运行,这个两个区别。