iOS多线程之GCD

时间:2021-10-24 05:16:24

介绍:

GCD,全称Grand Central Dispatch,是苹果公司开发的技术,以优化的应用程序支持多核心处理器和其他的对称多处理系统的系统。这建立在任务并行执行的线程池模式的基础上的。它首次发布在Mac OS X 10.6 ,iOS 4及以上可用。

设计:

GCD的工作原理是:让程序平行排队的特定任务,根据可用的处理资源,安排他们在任何可用的处理器核心上执行任务。

一个任务可以是一个函数(function)或者是一个block。 GCD的底层依然是用线程实现,不过这样可以让程序员不用关注实现的细节。

GCD中的FIFO队列称为dispatch queue,它可以保证先进来的任务先得到执行。

dispatch queue分为两种生成方式,即:

第一种   通过dispatch_queue_create生成,先介绍一下dispatch queue种类,

Serial 

又称为private dispatch queues,同时只执行一个任务。Serial queue通常用于同步访问特定的资源或数据。当你创建多个Serial queue时,虽然它们各自是同步执行的,但Serial queue与Serial queue之间是并发执行的。

Concurrent 

又称为global dispatch queue,可以并发地执行多个任务,但是执行完成的顺序是随机的。这里要强调一下,并行执行的处理数量取决于当先系统的状态,即iOS和OS X基于Dispatch Queue中的处理数、CPU核数、CPU负荷等当前状态。

使用dispatch_queue_create可生成任意多个Dispatch Queue

dispatch_queue_t  firstDispatch=dispatch_queue_create("myFirstDispatch", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(firstDispatch, ^{
NSLog(@"myFirstDispatch");
});

这样便创建了一个 Dispatch Queue,还需注意的一点是,如果过多的使用线程,就会消耗大量内存,引起大量的上下文切换,大幅度降低系统的响应性能。

第二种 通过dispatch_get_main_queue,dispatch_get_global_queue生成

系统提供了两个dispatch queue,那就是Main Dispatch Queue和Global Dispatch Queue,

Main Dispatch Queue即我们所说的主线程,关于界面更新的一些操作要在此线程中进行。

dispatch_queue_t mainDispatch=dispatch_get_main_queue();

这样便取到了主线程,可以移步做一些操作,

dispatch_async(mainDispatch, ^{
NSLog(@"mainDispatchHigh");
});

Global Dispatch Queue是所有应用程序都能够使用的Concurrent Dispatch Queue,它有4个执行优先级,分别是高优先级(High Priority)、默认优先级(Default Priority)、低优先级(Low Priority)和后台优先级(Background Priority)。

    dispatch_queue_t mainDispatch=dispatch_get_main_queue();
    dispatch_queue_t globalDispatchHigh=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);    dispatch_queue_t globalDispatchDefault=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);    dispatch_queue_t globalDispatchLow=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);    dispatch_queue_t globalDisaptchBackgroud=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);    dispatch_async(globalDispatchHigh, ^{      dispatch_async(mainDispatch, ^{          NSLog(@"globalDispatchHigh");      });    });    dispatch_async(globalDispatchLow, ^{        dispatch_async(mainDispatch, ^{            NSLog(@"globalDispatchLow");        });    });    dispatch_async(globalDisaptchBackgroud, ^{        dispatch_async(mainDispatch, ^{            NSLog(@"globalDisaptchBackgroud");        });    });    dispatch_async(globalDispatchDefault, ^{        dispatch_async(mainDispatch, ^{            NSLog(@"globalDispatchDefault");        });    });

打印的结果是

2016-11-17 11:08:48.426 gcdDemo[3221:60577] globalDispatchHigh
2016-11-17 11:08:48.427 gcdDemo[3221:60577] globalDispatchDefault
2016-11-17 11:08:48.427 gcdDemo[3221:60577] globalDispatchLow
2016-11-17 11:08:48.427 gcdDemo[3221:60577] globalDisaptchBackgroud
一些其他的方法

1、dispatch_set_target_queue
 

dispatch_queue_create函数生成的Dispatch Queue不管是Serial Dispatch Queue还是Concurrent Dispatch Queue,都是用与Global Dispatch Queue相同的优先级,而变更生成的Dispatch Queue则用到了dispatch_set_target_queue。

dispatch_async(globalDispatchHigh, ^{

      dispatch_async(mainDispatch, ^{

          NSLog(@"globalDispatchHigh");

      });

    });

//dispatch_set_target_queue

    dispatch_queue_t  secondDispatch=dispatch_queue_create("secondDispatch", DISPATCH_QUEUE_CONCURRENT);

    dispatch_async(secondDispatch, ^{

        NSLog(@"secondDispatch");

    });

    dispatch_set_target_queue(secondDispatch, globalDispatchHigh);

2、 dispatch_after

我们经常会遇到这样的情况,延时几秒后执行某一程序,除了可以使用
[ self performSelector:<#(nonnull SEL)#> withObject:<#(nullable id)#> afterDelay:<#(NSTimeInterval)#>] 之外,还可以使用dispatch_after方法。

 //dispatch_after
dispatch_time_t time=dispatch_time(DISPATCH_TIME_NOW, 10*NSEC_PER_SEC);
dispatch_after(time, dispatch_get_main_queue(), ^{
NSLog(@"十秒后执行");
});
这样便会在十秒后再打印了。

3、dispatch_group_create
使用Serial queue时将想执行的处理全部加到该Serial Dispatch Queue中并最后执行结束处理,但怎么在concurrent queue中这么做呢,这里就会用到dispatch_group_create。

 //dispatch_group_create
dispatch_group_t group=dispatch_group_create();
dispatch_group_async(group, secondDispatch, ^{
NSLog(@"group-----1");
});
dispatch_group_async(group, secondDispatch, ^{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 3*NSEC_PER_SEC), mainDispatch, ^{
NSLog(@"group-----2");
});
});
dispatch_group_async(group, secondDispatch, ^{
NSLog(@"group-----3");
});
dispatch_group_notify(group, secondDispatch, ^{
NSLog(@"finish");
});

long result=dispatch_group_wait(group, dispatch_time(DISPATCH_TIME_NOW, 0.1*NSEC_PER_SEC));

    if (result==0) {

        NSLog(@"chenggongjieshu");

    }else{

        NSLog(@"zhixingzhong");

    }

运行结果

2016-11-17 16:35:46.229 gcdDemo[6713:185629] group-----1
2016-11-17 16:35:46.229 gcdDemo[6713:185609] group-----3
2016-11-17 16:35:46.230 gcdDemo[6713:185569] chenggongjieshu
2016-11-17 16:35:46.230 gcdDemo[6713:185629] finish
2016-11-17 16:35:49.230 gcdDemo[6713:185569] group-----2

这里的group-----2最后出现是因为我加了一个延迟。可以看到,我们使用 dispatch_group_create 可以在结束时使用 dispatch_group_notify 来做一些操作。

dispatch_group_wait可以在指定时间后判断是否结束,result==0则是结束状态,非零则还在运行。


GCD还有很多其他用法,可以参考官方文档