iOS多线程网络之GCD进阶

来源:互联网 发布:神马软件 编辑:程序博客网 时间:2024/06/07 10:19

前言

前面总结了GCD的简单使用,iOS多线程网络之GCD,这次在总结一下GCD稍微深入一点的知识

死锁情况

产生场景

当向当前串行队列中发布一个同步任务,就会发生死锁现象

dispatch_sync(dispatch_get_main_queue(), ^{    NSLog(@"xxxxxx");});

我们向当前的主队列中发布一个同步任务,发生死锁,直接崩溃

产生原因

当我们将一个同步任务加入到主队列中的时候,因为主队列是同步队列,所以说任务要在dispatch_sync 执行完成之后才会去执行,但是dispatch_sync 是同步的,要在任务执行完毕之后才算是结束,所以说,主队列中的两个任务互相等待,导致死锁。

解决方法

一般的,我们不会向主队列中发布同步任务,而且dispatch_sync 也不是经常用,一般都是使用dispatch_async,除非为了保证队列中的执行顺序,可能会使用,但是后者的优势非常明显,不会造成死锁现象,而且可能充分利用CPU的利用率,提高了程序的运行速度,如果必须使用dispatch_sync 的话,需要注意所添加队列。

GCD任务组

假设有这样一个场景:有3个任务A,B,C,任务B需要在任务A和任务C执行完毕之后才执行,但是我们又想实现异步执行,怎么办呢?这种场景经常出现在异步加载图片的时候,有的时候需要下载多张图片,在多张图片下载完毕之后再执行其他操作。

这个时候就需要GCD中的任务组dispatch_group_t 了,

dispatch_group_t group = dispatch_group_create();dispatch_queue_t queue = dispatch_get_global_queue(0, 0);dispatch_group_async(group, queue, ^{    NSLog(@"333333");});dispatch_group_async(group, queue, ^{    NSLog(@"111111");});dispatch_group_notify(group, queue, ^{    NSLog(@"222222");});

在使用dispatch_group_create 创建一个任务组之后,就可以向其中中添加任务了,因为我们需要异步操作,所以说参数使用并行队列。
在最后,使用dispatch_group_notify 来表示执行完任务A和任务C之后执行任务B。

GCD的暂停和恢复

在NSOperation中,有很方便的暂停任务和恢复任务的方法,在GCD中,同样有着这样的功能
* 暂停某一个队列

dispatch_suspend(queue);
  • 恢复某一个队列
dispatch_resume(queue);

在进行这两个操作的时候,不会对队列中已经执行完毕的任务有影响,暂停之后,队列中没有执行的任务会暂停执行。

GCD实现单例模式

在一个应用程序中,有的时候会有相同的界面和功能,且不会改变,这个时候,为了节省内存和提高流畅度,我们可以保证一个界面只创建一个,然后每次使用的时候都是那个界面,怎么实现呢?懒加载?肯定是不行的,在当前类使用懒加载是没有问题的,但是在另一个类中再次使用呢,就会出现问题,所以,我们需要使用一个设计模式—-单例设计模式,来保证在程序中,只会开辟一次内存来实现界面的创建和功能。

一般的我们可以使用GCD来实现单例模式,dispathc_once 函数可以确保block在程序运行中只会运行一次,而且它是线程安全的,不会出现多个对象同时访问同一块内存而出现的问题。

例如我们要创建一个People类的单例:

+ (People *)sharePeople{    static People *sharedPeople = nil;    static dispatch_once_t once;    dispatch_once($once, ^{        sharedPeople = [[People alloc] init];    });    return sharePeople;}

创建一个值为 nil 的 sharedPeople静态对象,然后把它的初始化代码放到 dispatch_once 中完成。

这样,只有第一次调用 sharedPeople 方法时才会进行对象的初始化,之后获取就不会新建对象,也就不会开辟新的内存了。

最后

那么就先说到这里啦,有疑问和不足请务必要通知我!!!同时也欢迎大家关注和顶一下!嘿嘿嘿!

欢迎来到我的博客,我是AnICoo1,我喂自己袋盐
有错误请评论指出或联系我,不胜感激!

个人邮箱:helloiamclh@gmail.com

转载请注明出处,毕竟写了这么多也不容易,谢谢!

0 0