美文网首页
GCD使用总结

GCD使用总结

作者: Hardy_Hu | 来源:发表于2017-08-28 22:52 被阅读0次

多线程GCD是基于task使用的,API都是C语言实现的。iOS6 之后由于dispatch对象已经支持ARC,所以在ARC工程下,不用再担心GCD生命周期问题了。

一. GCD队列

队列有串行队列和并行队列。串行队列一次只能执行一个任务,只有一个任务执行完成之后才能进行下一个任务; 并行队列可以同时执行多个任务, 系统会维护一个线程池来保证并行队列的执行。

1.1 队列的创建
// 串行队列
dispatch_queue_t  serialQueue = dispatch_queue_create("yourQueueId.com", DISPATCH_QUEUE_SERIAL);
// 并行队列
dispatch_queue_t  concurrentQueue = dispatch_queue_create("yourQueueId.com", DISPATCH_QUEUE_CONCURRENT);

队列创建的函数dispatch_queue_create(), 使用时只需要传入队列的名字和属性即可。

label 参数: 队列的名字,便于识别
attr 参数: 队列的属性, 串行队列(DISPATCH_QUEUE_SERIAL)或并行队列(DISPATCH_QUEUE_CONCURRENT)
创建函数: dispatch_queue_create(const char *_Nullable label,
dispatch_queue_attr_t _Nullable attr)

如果要申明一个dispatch queue, 可以使用strong

@property (nonatomic, strong) dispatch_queue_t oneQueue;

1.2 多线程的开启

GCD下多线程的开启有两种方法,且需要队列配合,开启多线程的方法有同步多线程和异步多线程。

// 创建串行队列
dispatch_queue_t  q = dispatch_queue_create("yourQueueId.com", DISPATCH_QUEUE_SERIAL);
// 开启同步多线程
dispatch_sync(q, ^{
        NSLog(@" %@----开启多线程", [NSThread currentThread]);
    });

// 创建串行队列
dispatch_queue_t  queue = dispatch_queue_create("myQueueId.com", DISPATCH_QUEUE_SERIAL);
// 开启异步多线程
dispatch_async(queue, ^{
        NSLog(@" %@----开启多线程", [NSThread currentThread]);
    });

这样就开启了一个多线程,系统就会帮我们管理生命周期,不需要我们去手动开启、关闭、销毁。好处就是我们不需要关心内存问题,坏处是自己不能进行线程的暂停等操作。

异步多线程在开启后,会新开辟一个线程去执行block中代码,当前线程依然继续往下执行。

同步多线程在开启后,不会新开辟一个线程,他会先执行block里面的代码,然后继续多线程后面的代码。

- (void)viewDidLoad {
    [super viewDidLoad];
    
    NSLog(@" %@----当前线程", [NSThread currentThread]);
    NSLog(@"---->1 ");
    dispatch_queue_t q = dispatch_queue_create("yourQueueId.com", DISPATCH_QUEUE_SERIAL);
    dispatch_sync(q, ^{
        
        NSLog(@" %@----开启多线程", [NSThread currentThread]);
        NSLog(@" --->2");
    });
    
    
    dispatch_queue_t queue = dispatch_queue_create("myQueueId.com", DISPATCH_QUEUE_SERIAL);
    dispatch_async(queue, ^{
        
        NSLog(@" %@----再开启一个多线程", [NSThread currentThread]);
        NSLog(@" --->3");
    });
    
   NSLog(@" --->4");
}

看下我们的打印结果


打印结果.png

可以看到开启同步线程时并没有新建一个,且打印顺序也是顺序的;开启异步线程时,新开辟了一个线程地址,且打印顺序也不是固定的(可能先4后3, 也可能是先3后4)。

我们可以这样理解同步线程和异步线程:

开始时只有我一个人在做某事,某个时刻领导又有了个新任务,如果我们使用同步线程,这时还是只有我自己做事,只是先让我做这个新任务,等我把新任务完成后再继续之前的事情;这时如果我们使用异步线程,就相对于我们向领导申请调了一个人过来帮忙做新任务,我自己还是继续做之前的事情。

我们也可以这样理解串行队列和并行队列:

串行队列:我自己手头上有多个任务时,只能按部就班按照任务被分配给我的时间,依次执行,当上个任务执行完后,才能执行新任务。
并行队列: 我手头上同时有多个任务,领导让我们同时做这几个任务,哪个任务会先完成,我们不能确定,但最终所有的任务都会被完成。

总结:

所以同步线程是一个人在做事,异步线程是多个人在做事;串行队列是一个人同时只能做一个事情,并行队列是一个人同时做多个事情。

二. GCD多线程的应用

2.1 多线程的延迟启动

在上面我们开启一个多线程是即时的,如果我们想定时开启怎么做?别担心,系统给我们提供了个延迟启动的APIdispatch_after。

   // NSEC_PER_SEC 表示秒
   //  NSEC_PER_MSEC 表示毫秒
    // NSEC_PRE_USEC 表示微秒
    NSLog(@"开始");
    dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW,(2 * NSEC_PER_SEC));
    dispatch_after(time,dispatch_get_main_queue(),^{
        NSLog(@"延迟启动");
    });
2.2 三种创建队列的方法

在1.1节中我们学会了使用dispatch_queue_create创建串行和并行队列,加上系统给我们创建的2种独一无二的队列,我们一种就有3种创建队列的方法。

//系统创建的串行主队列
dispatch_queue_t mainQueue = dispatch_get_main_queue() ;
    
// 系统创建的全局并行队列
dispatch_queue_t globalQueue = dispatch_get_global_queue(0, 0);
    
// 自定义队列
dispatch_queue_t myQueue = dispatch_queue_create("myQueue.com", DISPATCH_QUEUE_SERIAL);
2.3 dispatch_barrier_async

我们知道串行队列是按照FIFO顺序执行的,所以可以预测哪个串行队列最后执行完

    dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL);
    
    dispatch_async(queue, ^{
        NSLog(@"----1-----%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"----2-----%@", [NSThread currentThread]);
    });
    
    dispatch_async(queue, ^{
        NSLog(@"----3-----%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"----4-----%@", [NSThread currentThread]);
    });

可以看到输出顺序是可以预测的。由于同步线程是按照顺序执行的,所以输出顺序也是可控的。


串行队列.png

但是改为并行队列

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

就会发现输出结果顺序就不确定了


顺序不确定.png

如果我们想要等1和2先执行完后再去执行3和4, 我们知道GCD并没有提供给我们对多线程的生命周期的管理,怎么办了?查资料刚好有个API dispatch_barrier_async可以满足我们的要求,我们在1,2后面加上barrier_async函数,如下

 dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_async(queue, ^{
        NSLog(@"----1-----%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"----2-----%@", [NSThread currentThread]);
    });
    dispatch_barrier_async(queue, ^{
        NSLog(@"----barrier-----%@", [NSThread currentThread]);
    });
    
    dispatch_async(queue, ^{
        NSLog(@"----3-----%@", [NSThread currentThread]);
    });
    dispatch_async(queue, ^{
        NSLog(@"----4-----%@", [NSThread currentThread]);
    });

可以运行下,看到结果正是我们所期望的,虽然1和2的顺序无法确定,但是是等1,2都执行完后才开始执行3,4的。


barrier_async作用.png
2.4 dispatch_group

在2.3节中我们知道dispatch_barrier_async可以控制某个线程执行完后再执行另外线程,那如果我们想知道某几个多线程什么时候执行完毕怎么操作,恰好系统也提供了一个API: dispatch_group

    dispatch_queue_t dispatchQueue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_group_t dispatchGroup = dispatch_group_create();
    dispatch_group_async(dispatchGroup, dispatchQueue, ^(){
         NSLog(@"----1-----%@", [NSThread currentThread]);
    });
    dispatch_group_async(dispatchGroup, dispatchQueue, ^(){
        NSLog(@"----2-----%@", [NSThread currentThread]);
    });
    dispatch_group_async(dispatchGroup, dispatchQueue, ^(){
        NSLog(@"----3-----%@", [NSThread currentThread]);
    });
    dispatch_group_async(dispatchGroup, dispatchQueue, ^(){
        NSLog(@"----4-----%@", [NSThread currentThread]);
    });
    dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^(){
        NSLog(@"end");
    });

运行下,结果如下,可以看到通过 dispatch_group我们就能准确知道多个异步线程什么时候都执行完毕。


dispatch_group.png

相关文章

  • iOS多线程:GCD Group、Barrier和NSOpera

    GCD系列文章 GCD任务和队列使用详解 本文主要总结GCD Group、Barrier和NSOperationQ...

  • iOS进阶-多线程-GCD

    GCD 概念 GCD队列 使用总结 实用api 实用遇到的坑 一、 概念 GCD(grand central di...

  • 高级iOS面试题全纪录

    iOS基础: 多线程使用,gcd跟operation区别,怎么取消正在执行的gcd任务 GCD 系列知识总结 NS...

  • GCD使用总结

    多线程GCD是基于task使用的,API都是C语言实现的。iOS6 之后由于dispatch对象已经支持ARC,所...

  • iOS 开发之 GCD 不同场景使用

    iOS 开发之 GCD 不同场景使用 本文在iOS 开发值 GCD 基础 的基础上,继续总结了 GCD 的一些AP...

  • iOS多线程之GCD浅析

    本文用来介绍 iOS 多线程中 GCD 的相关知识以及使用方法,分析GCD的原理,总结GCD的用法和需要注意的地方...

  • iOS多线程:『GCD』详尽总结

    iOS多线程:『GCD』详尽总结 iOS多线程:『GCD』详尽总结

  • IOS开发 GCD产生死锁的总结

    在IOS开发中GCD的使用频率很高,但是使用不当,则会产生死锁,以下是我的对GCD产生死锁的总结。 了解死锁之前首...

  • GCD使用的总结

    GCD(Grand Central Dispatch)可以说是Mac、iOS开发中的一大“利器”,本文就总结一些有...

  • iOS高级进阶之多线程 (一)

    关注我,连载进行中....iOS 当中的多线程方案. 总结如下图:我平时使用最多的是 gcd. 不论是 GCD ....

网友评论

      本文标题:GCD使用总结

      本文链接:https://www.haomeiwen.com/subject/ryagdxtx.html