• GCD队列、同步异步

    发布:51Code 时间: 2018-04-10 14:14

  • GCD的队列有两种,一种是串行队列,一种是并发队列。 串行队列: 任务按往队列里的添加先后顺序执行,先进先出(FIFO),前一个任务执行完再开始执行下一个任务。(我们开发中主线程...

  • GCD的队列有两种,一种是串行队列,一种是并发队列。

    串行队列:

    任务按往队列里的添加先后顺序执行,先进先出(FIFO),前一个任务执行完再开始执行下一个任务。(我们开发中主线程队列就是一个串行队列,所以我们经常在主线程写的一般任务(不考虑多线程),都是顺序执行的)。

    注意一个串行队列里只有一个线程。

    并发队列:

    任务会在这个队列中新开线程,并发同时执行(无序)。

    我们GCD使用常伴有dispatch_sync和dispatch_async,这就是同步执行和异步执行。

    同步和异步

    同步执行:任务都在当前线程中执行,执行过程中会阻塞当前线程。

    异步执行:任务会开辟新的线程,并在新的线程中执行,不会阻塞当前线程。

    注意

    1.同步执行没有开启新线程的能力, 所有的任务都只能在当前线程执行

    2.异步执行有开启新线程的能力, 但是, 有开启新线程的能力, 也不一定会利用这种能力, 也就是说, 异步执行是否开启新线程, 需要具体问题具体分析

    3.并发队列中的任务会放到不同的线程中去执行.

    4.串行队列中的任务只会放到同一线程中去执行.

    基本介绍算是完了,队列有2种,执行方式有2种,那么他们互相组合会是什么情况呢?

    很显然,它们可以组合成4种情况:

    1).串行同步队列:任务都在当前线程执行(同步),并且顺序执行(串行)

    2).串行异步队列:任务都在开辟的新的子线程中执行(异步),并且顺序执行(串行)

    3).并发同步队列:任务都在当前线程执行(同步),但是是顺序执行的(并没有体现并发的特性)

    4).并发异步队列:任务在开辟的多个子线程中执行(异步),并且是同时执行的(并发)

    验证:

    1.串行同步队列

    代码直接写在viewDidLoad里

    dispatch_queue_t queue = dispatch_queue_create("serialQueue", DISPATCH_QUEUE_SERIAL);

        dispatch_sync(queue, ^{

            NSLog(@"task1");

            NSLog(@"task1---%@",[NSThread currentThread]);

        });

        

        dispatch_sync(queue, ^{

            NSLog(@"task2");

            NSLog(@"task2---%@",[NSThread currentThread]);

        });

        

        dispatch_sync(queue, ^{

            NSLog(@"task3");

            NSLog(@"task3---%@",[NSThread currentThread]);

        });

        

        NSLog(@"task4");

        NSLog(@"task4---%@",[NSThread currentThread]);

    结果

    2018-01-29 11:26:00.511 GCD[72214:3984485] task1

    2018-01-29 11:26:00.512 GCD[72214:3984485] task1---<NSThread: 0x6080002610c0>{number = 1, name = main}

    2018-01-29 11:26:00.512 GCD[72214:3984485] task2

    2018-01-29 11:26:00.512 GCD[72214:3984485] task2---<NSThread: 0x6080002610c0>{number = 1, name = main}

    2018-01-29 11:26:00.512 GCD[72214:3984485] task3

    2018-01-29 11:26:00.513 GCD[72214:3984485] task3---<NSThread: 0x6080002610c0>{number = 1, name = main}

    2018-01-29 11:26:00.513 GCD[72214:3984485] task4

    2018-01-29 11:26:00.513 GCD[72214:3984485] task4---<NSThread: 0x6080002610c0>{number = 1, name = main}

    分析:任务是在当前线程(当前是主线程)顺序执行的。这也验证了

    串行同步队列:任务都在当前线程执行(同步),并且顺序执行(串行)

    这里需要注意的是代码直接在viewDidLoad里写的,主队列也是一个串行队列,但在主线程中使用主队列同步执行会造成死锁,这里不讨论这个。另外,若在viewDidLoad新开一个子线程,去执行代码,结果是同样可以验证的:

    [NSThread detachNewThreadSelector:@selector(threadAction) toTarget:self withObject:nil];

     

    -(void)threadAction{

        dispatch_queue_t queue = dispatch_queue_create("serialQueue", DISPATCH_QUEUE_SERIAL);

        dispatch_sync(queue, ^{

            NSLog(@"task1");

            NSLog(@"task1---%@",[NSThread currentThread]);

        });

        

        dispatch_sync(queue, ^{

            NSLog(@"task2");

            NSLog(@"task2---%@",[NSThread currentThread]);

        });

        

        dispatch_sync(queue, ^{

            NSLog(@"task3");

            NSLog(@"task3---%@",[NSThread currentThread]);

        });

        

        NSLog(@"task4");

        NSLog(@"task4---%@",[NSThread currentThread]);

     

    2018-01-29 11:27:31.056 GCD[72230:3986823] task1

    2018-01-29 11:27:31.056 GCD[72230:3986823] task1---<NSThread: 0x600000075f80>{number = 3, name = (null)}

    2018-01-29 11:27:31.057 GCD[72230:3986823] task2

    2018-01-29 11:27:31.057 GCD[72230:3986823] task2---<NSThread: 0x600000075f80>{number = 3, name = (null)}

    2018-01-29 11:27:31.058 GCD[72230:3986823] task3

    2018-01-29 11:27:31.059 GCD[72230:3986823] task3---<NSThread: 0x600000075f80>{number = 3, name = (null)}

    2018-01-29 11:27:31.059 GCD[72230:3986823] task4

    2018-01-29 11:27:31.059 GCD[72230:3986823] task4---<NSThread: 0x600000075f80>{number = 3, name = (null)}

    2.串行异步队列

    dispatch_queue_t queue = dispatch_queue_create("serialQueue", DISPATCH_QUEUE_SERIAL);

        dispatch_async(queue, ^{

            NSLog(@"task1");

            NSLog(@"task1---%@",[NSThread currentThread]);

        });

        

        dispatch_async(queue, ^{

            NSLog(@"task2");

            NSLog(@"task2---%@",[NSThread currentThread]);

        });

        

        dispatch_async(queue, ^{

            NSLog(@"task3");

            NSLog(@"task3---%@",[NSThread currentThread]);

        });

        

        NSLog(@"task4");

        NSLog(@"task4---%@",[NSThread currentThread]);

     

    2018-01-29 11:30:19.254 GCD[72269:3990336] task1

    2018-01-29 11:30:19.254 GCD[72269:3990288] task4

    2018-01-29 11:30:19.254 GCD[72269:3990288] task4---<NSThread: 0x60800006df00>{number = 1, name = main}

    2018-01-29 11:30:19.254 GCD[72269:3990336] task1---<NSThread: 0x60000007a9c0>{number = 3, name = (null)}

    2018-01-29 11:30:19.255 GCD[72269:3990336] task2

    2018-01-29 11:30:19.255 GCD[72269:3990336] task2---<NSThread: 0x60000007a9c0>{number = 3, name = (null)}

    2018-01-29 11:30:19.255 GCD[72269:3990336] task3

    2018-01-29 11:30:19.255 GCD[72269:3990336] task3---<NSThread: 0x60000007a9c0>{number = 3, name = (null)}

     

    2018-01-29 11:32:01.533 GCD[72278:3992351] task4

    2018-01-29 11:32:01.533 GCD[72278:3992391] task1

    2018-01-29 11:32:01.534 GCD[72278:3992351] task4---<NSThread: 0x60800006d580>{number = 1, name = main}

    2018-01-29 11:32:01.534 GCD[72278:3992391] task1---<NSThread: 0x6080000771c0>{number = 3, name = (null)}

    2018-01-29 11:32:01.534 GCD[72278:3992391] task2

    2018-01-29 11:32:01.534 GCD[72278:3992391] task2---<NSThread: 0x6080000771c0>{number = 3, name = (null)}

    2018-01-29 11:32:01.534 GCD[72278:3992391] task3

    2018-01-29 11:32:01.535 GCD[72278:3992391] task3---<NSThread: 0x6080000771c0>{number = 3, name = (null)}

    分析:主线程异步调用,我们先分析加到队列里的task任务1、2、3,确实都是在开辟了的新线程<NSThread: 0x60000007a9c0>{number = 3, name = (null)}上顺序执行的,关于task4,由于是异步的,它也没加入队列queue,啥时候输出就看电脑心情了...验证结果:

    串行异步队列:任务都在开辟的新的子线程中执行(异步),并且顺序执行(串行)

    这里需要注意,由于新创建了串行线程,所以任务会在新开辟的线程上执行,若是直接在主队列异步调用,任务执行都在主线程上。

    3.并发同步队列

    dispatch_queue_t queue = dispatch_queue_create("concurrentQueue", DISPATCH_QUEUE_CONCURRENT);

        dispatch_sync(queue, ^{

            NSLog(@"task1");

            NSLog(@"task1---%@",[NSThread currentThread]);

        });

        

        dispatch_sync(queue, ^{

            NSLog(@"task2");

            NSLog(@"task2---%@",[NSThread currentThread]);

        });

        

        dispatch_sync(queue, ^{

            NSLog(@"task3");

            NSLog(@"task3---%@",[NSThread currentThread]);

        });

        

        NSLog(@"task4");

        NSLog(@"task4---%@",[NSThread currentThread]);

     

    2018-01-29 11:40:40.274 GCD[72316:3998532] task1

    2018-01-29 11:40:40.274 GCD[72316:3998532] task1---<NSThread: 0x60800006ce80>{number = 1, name = main}

    2018-01-29 11:40:40.274 GCD[72316:3998532] task2

    2018-01-29 11:40:40.274 GCD[72316:3998532] task2---<NSThread: 0x60800006ce80>{number = 1, name = main}

    2018-01-29 11:40:40.274 GCD[72316:3998532] task3

    2018-01-29 11:40:40.275 GCD[72316:3998532] task3---<NSThread: 0x60800006ce80>{number = 1, name = main}

    2018-01-29 11:40:40.275 GCD[72316:3998532] task4

    2018-01-29 11:40:40.275 GCD[72316:3998532] task4---<NSThread: 0x60800006ce80>{number = 1, name = main}

    分析:任务是在当前线程(是主线程没有开辟新线程)顺序执行的,跟串行同步一样,虽是并发队列,却不能并发。得到验证结果:

    并发同步队列:任务都在当前线程执行(同步),但是是顺序执行的(并没有体现并发的特性)

    4.并发异步队列

    dispatch_queue_t queue = dispatch_queue_create("concurrentQueue", DISPATCH_QUEUE_CONCURRENT);

        dispatch_async(queue, ^{

            NSLog(@"task1");

            NSLog(@"task1---%@",[NSThread currentThread]);

        });

        

        dispatch_async(queue, ^{

            NSLog(@"task2");

            NSLog(@"task2---%@",[NSThread currentThread]);

        });

        

        dispatch_async(queue, ^{

            NSLog(@"task3");

            NSLog(@"task3---%@",[NSThread currentThread]);

        });

        

        NSLog(@"task4");

        NSLog(@"task4---%@",[NSThread currentThread]);

     

    2018-01-29 11:47:23.235 GCD[72367:4005184] task2

    2018-01-29 11:47:23.235 GCD[72367:4005156] task4

    2018-01-29 11:47:23.235 GCD[72367:4005183] task1

    2018-01-29 11:47:23.235 GCD[72367:4005186] task3

    2018-01-29 11:47:23.236 GCD[72367:4005156] task4---<NSThread: 0x600000262a80>{number = 1, name = main}

    2018-01-29 11:47:23.236 GCD[72367:4005184] task2---<NSThread: 0x608000267500>{number = 3, name = (null)}

    2018-01-29 11:47:23.236 GCD[72367:4005183] task1---<NSThread: 0x60000026f380>{number = 4, name = (null)}

    2018-01-29 11:47:23.236 GCD[72367:4005186] task3---<NSThread: 0x608000267540>{number = 5, name = (null)}

     

    2018-01-29 11:48:23.070 GCD[72375:4006982] task1

    2018-01-29 11:48:23.070 GCD[72375:4006934] task4

    2018-01-29 11:48:23.070 GCD[72375:4006984] task3

    2018-01-29 11:48:23.070 GCD[72375:4006981] task2

    2018-01-29 11:48:23.070 GCD[72375:4006934] task4---<NSThread: 0x608000068300>{number = 1, name = main}

    2018-01-29 11:48:23.070 GCD[72375:4006982] task1---<NSThread: 0x60000006db40>{number = 3, name = (null)}

    2018-01-29 11:48:23.071 GCD[72375:4006984] task3---<NSThread: 0x608000074300>{number = 4, name = (null)}

    2018-01-29 11:48:23.071 GCD[72375:4006981] task2---<NSThread: 0x60000006d140>{number = 5, name = (null)}

     

    2018-01-29 11:48:42.930 GCD[72380:4007604] task4

    2018-01-29 11:48:42.930 GCD[72380:4007680] task2

    2018-01-29 11:48:42.930 GCD[72380:4007683] task1

    2018-01-29 11:48:42.930 GCD[72380:4007681] task3

    2018-01-29 11:48:42.930 GCD[72380:4007604] task4---<NSThread: 0x6000000742c0>{number = 1, name = main}

    2018-01-29 11:48:42.930 GCD[72380:4007680] task2---<NSThread: 0x60800007d680>{number = 3, name = (null)}

    2018-01-29 11:48:42.930 GCD[72380:4007683] task1---<NSThread: 0x60000007f500>{number = 4, name = (null)}

    2018-01-29 11:48:42.930 GCD[72380:4007681] task3---<NSThread: 0x60800007d5c0>{number = 5, name = (null)}

    分析:先看task4吧,没有加入队列,所以肯定是在主线程执行的,由于异步,啥时候执行还是要看电脑心情...好了,言归正传,我们看加入到并发队列里的任务1、2、3,三个运行结果证明它们是在不同的线程中无序执行的,每个任务都开辟了新的线程去执行,并且执行顺序是无序的,体现了并发的特性。所以我们经常也是使用这种方式做一些需求。验证结果:

    并发异步队列:任务在开辟的多个子线程中执行(异步),并且是同时执行的(并发)

    最后总结一下:文章开头理论再看一遍!不懂继续写,边写边理解。

    原文作者:_清墨
    上文内容来自:简书
    博为峰对此不表示赞同或者反对,也不为其提供证明,仅供阅读者交流参考。
    上文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编caoxiaoyan@51testing.com,我们将立即处理。
  • 上一篇:轻量级低风险 iOS 热更新方案

    下一篇:专业程序员的标准,你达到了吗?

相关资讯
网站导航
Copyright(C)51Code软件开发网 2003-2018 , 沪ICP备05003035号