GCD常用方法及应用场景

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/aaaaazq/article/details/82222601

开发过程中,出现耗时操作造成界面卡顿是常见的问题之一,问题原因就是因为耗时操作阻塞了主线程,所以要解决这类问题最简单的就是引进子线程,将耗时操作移出主线程,耗时操作完成后回到主线程中更新UI。
之前在做一个通讯录的时候,由于需要自己进行排序,所以第一次时需要将几千条的数据都拉下来然后处理,这是非常耗时的,直接放在主线程中网络请求然后各种处理数据会让界面卡死3到5秒。后来使用GCD的并发队列异步处理解决了,个人感觉非常的简单实用,关键代码如下:

dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue, ^{
       //耗时操作,如网络请求
        //请求完成之后,回到主线程更新UI
        dispatch_async(dispatch_get_main_queue(), ^{
            //更新UI操作
        });
    });

建议在开发过程中,页面的网络请求和耗时操作都可以以这种方式处理,一般每个页面的网络请求不会太多,不会造成并发数太大的问题,这也是用户体验和性能优化的一种,网络再慢也不会给用户带来卡顿的体验。
还有比较复杂一点的页面,可能存在多个操作,而某个操作依赖前几个操作完成之后才能开始,这个时候我们可以使用GCD的线程组,使用代码:

dispatch_group_t group = dispatch_group_create();
    dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_CONCURRENT);
    dispatch_group_async(group, queue, ^{
       //操作一
        for (int i = 0; i < 10; i ++) {
            NSLog(@"1------%@",[NSThread currentThread]);
        }
    });
    dispatch_group_async(group, queue, ^{
        //操作二
        for (int i = 0; i < 10; i ++) {
            NSLog(@"2------%@",[NSThread currentThread]);
        }
    });
    dispatch_group_async(group, queue, ^{
        //操作三
        for (int i = 0; i < 10; i ++) {
            NSLog(@"3------%@",[NSThread currentThread]);
        }
    });
    dispatch_group_notify(group, queue, ^{
        //最后的操作
        for (int i = 0; i < 10; i ++) {
            NSLog(@"notify------%@",[NSThread currentThread]);
        }
    });

我们先来看一下打印结果:

2018-08-30 15:04:19.178991+0800 GCD_demo[3996:227745] 1------<NSThread: 0x604000261d00>{number = 3, name = (null)}
2018-08-30 15:04:19.178995+0800 GCD_demo[3996:227743] 3------<NSThread: 0x60c00007d080>{number = 5, name = (null)}
2018-08-30 15:04:19.179000+0800 GCD_demo[3996:227746] 2------<NSThread: 0x60800027f0c0>{number = 4, name = (null)}
2018-08-30 15:04:19.179238+0800 GCD_demo[3996:227743] 3------<NSThread: 0x60c00007d080>{number = 5, name = (null)}
2018-08-30 15:04:19.179240+0800 GCD_demo[3996:227745] 1------<NSThread: 0x604000261d00>{number = 3, name = (null)}
2018-08-30 15:04:19.179243+0800 GCD_demo[3996:227746] 2------<NSThread: 0x60800027f0c0>{number = 4, name = (null)}
2018-08-30 15:04:19.179668+0800 GCD_demo[3996:227743] 3------<NSThread: 0x60c00007d080>{number = 5, name = (null)}
2018-08-30 15:04:19.179910+0800 GCD_demo[3996:227745] 1------<NSThread: 0x604000261d00>{number = 3, name = (null)}
2018-08-30 15:04:19.179940+0800 GCD_demo[3996:227746] 2------<NSThread: 0x60800027f0c0>{number = 4, name = (null)}
2018-08-30 15:04:19.179983+0800 GCD_demo[3996:227743] 3------<NSThread: 0x60c00007d080>{number = 5, name = (null)}
2018-08-30 15:04:19.180011+0800 GCD_demo[3996:227745] 1------<NSThread: 0x604000261d00>{number = 3, name = (null)}
2018-08-30 15:04:19.180341+0800 GCD_demo[3996:227746] 2------<NSThread: 0x60800027f0c0>{number = 4, name = (null)}
2018-08-30 15:04:19.180595+0800 GCD_demo[3996:227745] 1------<NSThread: 0x604000261d00>{number = 3, name = (null)}
2018-08-30 15:04:19.180753+0800 GCD_demo[3996:227743] 3------<NSThread: 0x60c00007d080>{number = 5, name = (null)}
2018-08-30 15:04:19.180920+0800 GCD_demo[3996:227746] 2------<NSThread: 0x60800027f0c0>{number = 4, name = (null)}
2018-08-30 15:04:19.181272+0800 GCD_demo[3996:227745] 1------<NSThread: 0x604000261d00>{number = 3, name = (null)}
2018-08-30 15:04:19.181380+0800 GCD_demo[3996:227743] 3------<NSThread: 0x60c00007d080>{number = 5, name = (null)}
2018-08-30 15:04:19.181513+0800 GCD_demo[3996:227746] 2------<NSThread: 0x60800027f0c0>{number = 4, name = (null)}
2018-08-30 15:04:19.181807+0800 GCD_demo[3996:227745] 1------<NSThread: 0x604000261d00>{number = 3, name = (null)}
2018-08-30 15:04:19.181906+0800 GCD_demo[3996:227743] 3------<NSThread: 0x60c00007d080>{number = 5, name = (null)}
2018-08-30 15:04:19.182027+0800 GCD_demo[3996:227746] 2------<NSThread: 0x60800027f0c0>{number = 4, name = (null)}
2018-08-30 15:04:19.182437+0800 GCD_demo[3996:227745] 1------<NSThread: 0x604000261d00>{number = 3, name = (null)}
2018-08-30 15:04:19.182531+0800 GCD_demo[3996:227743] 3------<NSThread: 0x60c00007d080>{number = 5, name = (null)}
2018-08-30 15:04:19.182616+0800 GCD_demo[3996:227746] 2------<NSThread: 0x60800027f0c0>{number = 4, name = (null)}
2018-08-30 15:04:19.182765+0800 GCD_demo[3996:227745] 1------<NSThread: 0x604000261d00>{number = 3, name = (null)}
2018-08-30 15:04:19.183371+0800 GCD_demo[3996:227743] 3------<NSThread: 0x60c00007d080>{number = 5, name = (null)}
2018-08-30 15:04:19.183427+0800 GCD_demo[3996:227746] 2------<NSThread: 0x60800027f0c0>{number = 4, name = (null)}
2018-08-30 15:04:19.183489+0800 GCD_demo[3996:227745] 1------<NSThread: 0x604000261d00>{number = 3, name = (null)}
2018-08-30 15:04:19.183509+0800 GCD_demo[3996:227743] 3------<NSThread: 0x60c00007d080>{number = 5, name = (null)}
2018-08-30 15:04:19.183644+0800 GCD_demo[3996:227746] 2------<NSThread: 0x60800027f0c0>{number = 4, name = (null)}
2018-08-30 15:04:19.184220+0800 GCD_demo[3996:227746] notify------<NSThread: 0x60800027f0c0>{number = 4, name = (null)}
2018-08-30 15:04:19.184694+0800 GCD_demo[3996:227746] notify------<NSThread: 0x60800027f0c0>{number = 4, name = (null)}
2018-08-30 15:04:19.185670+0800 GCD_demo[3996:227746] notify------<NSThread: 0x60800027f0c0>{number = 4, name = (null)}
2018-08-30 15:04:19.186316+0800 GCD_demo[3996:227746] notify------<NSThread: 0x60800027f0c0>{number = 4, name = (null)}
2018-08-30 15:04:19.186535+0800 GCD_demo[3996:227746] notify------<NSThread: 0x60800027f0c0>{number = 4, name = (null)}
2018-08-30 15:04:19.186660+0800 GCD_demo[3996:227746] notify------<NSThread: 0x60800027f0c0>{number = 4, name = (null)}
2018-08-30 15:04:19.187406+0800 GCD_demo[3996:227746] notify------<NSThread: 0x60800027f0c0>{number = 4, name = (null)}
2018-08-30 15:04:19.187940+0800 GCD_demo[3996:227746] notify------<NSThread: 0x60800027f0c0>{number = 4, name = (null)}
2018-08-30 15:04:19.188188+0800 GCD_demo[3996:227746] notify------<NSThread: 0x60800027f0c0>{number = 4, name = (null)}
2018-08-30 15:04:19.188589+0800 GCD_demo[3996:227746] notify------<NSThread: 0x60800027f0c0>{number = 4, name = (null)}

我们会发现,操作一、操作二和操作三是无序执行的,但是最后的操作是等前面的都执行完成之后才开始执行的。像这样的应用场景还是很多的,比如第三个网络请求的参数依赖于前两个网络请求的结果,就可以用这种方式来处理。
如果想要操作一、二、三也都顺序执行,可以使用串行队列。还可以使用enter和leave方法,用法如下:

dispatch_group_t group = dispatch_group_create();
    dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_CONCURRENT);
    dispatch_group_enter(group);
    dispatch_group_async(group, queue, ^{
       //操作一
        NSLog(@"111");
        dispatch_group_leave(group);
    });
    dispatch_group_async(group, queue, ^{
        //操作二
        NSLog(@"222");

    });
    dispatch_group_async(group, queue, ^{
        //操作三
        NSLog(@"333");

    });
    dispatch_group_notify(group, queue, ^{
        //最后的操作
        for (int i = 0; i < 10; i ++) {
            NSLog(@"notify------%@",[NSThread currentThread]);
        }
    });

打印结果:

2018-08-30 15:34:01.152524+0800 GCD_demo[4391:254500] 111
2018-08-30 15:34:01.152530+0800 GCD_demo[4391:254497] 333
2018-08-30 15:34:01.152524+0800 GCD_demo[4391:254498] 222
2018-08-30 15:34:01.152854+0800 GCD_demo[4391:254498] notify------<NSThread: 0x60c00027c900>{number = 3, name = (null)}
2018-08-30 15:34:01.153542+0800 GCD_demo[4391:254498] notify------<NSThread: 0x60c00027c900>{number = 3, name = (null)}
2018-08-30 15:34:01.153710+0800 GCD_demo[4391:254498] notify------<NSThread: 0x60c00027c900>{number = 3, name = (null)}
2018-08-30 15:34:01.153855+0800 GCD_demo[4391:254498] notify------<NSThread: 0x60c00027c900>{number = 3, name = (null)}
2018-08-30 15:34:01.154183+0800 GCD_demo[4391:254498] notify------<NSThread: 0x60c00027c900>{number = 3, name = (null)}
2018-08-30 15:34:01.154307+0800 GCD_demo[4391:254498] notify------<NSThread: 0x60c00027c900>{number = 3, name = (null)}
2018-08-30 15:34:01.154711+0800 GCD_demo[4391:254498] notify------<NSThread: 0x60c00027c900>{number = 3, name = (null)}
2018-08-30 15:34:01.154830+0800 GCD_demo[4391:254498] notify------<NSThread: 0x60c00027c900>{number = 3, name = (null)}
2018-08-30 15:34:01.154944+0800 GCD_demo[4391:254498] notify------<NSThread: 0x60c00027c900>{number = 3, name = (null)}
2018-08-30 15:34:01.155039+0800 GCD_demo[4391:254498] notify------<NSThread: 0x60c00027c900>{number = 3, name = (null)}

以上代码可以保证操作一执行完才开始操作二和操作三,需要注意的一点是enter和leave方法是成对出现的,如果用了enter,没有写leave的话,会造成notify无法执行。如果操作一、二、三种存在block代码,那么leave方法需要放在block中,否则block没执行完,就开始执行后面的操作了。
虽然说多线程在开发和面试中都被认为是重中之重,但是就实际开发过程中而言,用到的场景并没有提供的方法多,没必要死扣理论和知道的方法多少,会用来解决问题才是最重要的!

猜你喜欢

转载自blog.csdn.net/aaaaazq/article/details/82222601
今日推荐