iOS底层原理之GCD的任务与队列_henry_lei的博客-程序员信息网

技术标签: ios  

GCD

简介

Grand Central Dispatch(GCD)是 Apple 开发的一个多核编程的解决方法。它是一套纯 C 语言的 API,主要用于优化应用程序以支持多核处理器以及其他对称多处理系统。它是一个在线程池模式的基础上执行的并发任务。

GCD的优点

  • GCD支持多核并行计算
  • GCD自动管理线程的生命周期(线程的创建、调起、等待、销毁)
  • 使用者只需告知GCD执行任务

任务与队列

任务

任务即执行操作,就是线程中需要执行的代码。在GCD中就是放在block中执行的代码都是任务。任务分为同步任务(sync)异步任务(async)

  • 同步任务(sync):同步添加到队列当中,当前面的任务没有执行完毕时会一直等待,直到前面的任务执行完毕才会执行当前加入的任务。不可以在新的线程中执行,不具备开辟新的线程能力。
  • 异步任务(async):异步添加到队列当中,无需等待前面的任务执行完成才执行,加入队列就会执行。可以在新的线程中执行,具备开辟新的线程能力。注意:具备开启新线程的能力不代表一定开启新的线程

队列

指执行任务的队列,就是等待执行的任务列表,遵循先进先出IFFO原则。在GCD中有串行队列(Serial Dispatch Queue)并行队列(Concurrent Dispatch Queue),又叫并发队列

  • 串行队列(Serial Dispatch Queue):只开启一个线程,每次只有一个任务执行,任务执行完成后才会执行下一个任务。

  • 并行队列(Concurrent Dispatch Queue):可以让多个任务同时执行,可以开启多个线程来执行多个任务。

    注意:并发队列只有在异步函数下才有效

特殊队列

  • 串行主队列:一种串行的主队列,在主队列中调用不能在主线程中再次调用同步任务,否则会造成堵塞,但是可以在其他线程调用同步任务
  • 全局并发队列:一种全局的并发队列

队列与任务的创建

创建队列

  • 创建串行队列
//第一个参数是队列的名字,自定义;第二个参数表示是串行还是并发
//DISPATCH_QUEUE_SERIAL = NULL,因此DISPATCH_QUEUE_SERIAL可以用NULL代替创建串行队列
dispatch_queue_t queue = dispatch_queue_create("shifx", DISPATCH_QUEUE_SERIAL);
  • 创建并发队列
//第一个参数是队列的名字,自定义;第二个参数表示是串行还是并发
dispatch_queue_t queue = dispatch_queue_create("shifx", DISPATCH_QUEUE_CONCURRENT);

任务的创建

  • 创建同步任务
//创建同步任务(queue是队列)
dispatch_sync(queue, ^{

});

  • 创建异步任务
//创建异步任务(queue是队列)
dispatch_async(queue, ^{

});

队列与任务总结

综上所述,我们可以得出一共四种组合外加两种特殊的队列,即

  • 串行队列+同步执行
  • 并发队列+同步执行
  • 串行队列+异步执行
  • 并发队列+异步执行
  • 串行主队列
  • 全局并发队列

队列与任务组合使用

串行队列+同步执行

代码实现

-(void)serialSysncText {
    //串行队列
    dispatch_queue_t serial = dispatch_queue_create("shifx", DISPATCH_QUEUE_SERIAL);
    NSLog(@"串行同步任务开始");
    dispatch_sync(serial, ^{
        sleep(1);
        for (int i = 0; i<3; i++) {
            NSLog(@"串行同步任务1 = %d",i);
        }
    });
    dispatch_sync(serial, ^{
        sleep(1);
        for (int i = 0; i<3; i++) {
            NSLog(@"串行同步任务2 = %d",i);
        }
    });
    NSLog(@"串行同步任务结束");
}

运行结果

从运行结果当中,我们可以看到串行队列中的同步任务都是按照先后顺序依次执行的。

并发队列+同步任务

代码实现

-(void)concurrentAsysncText {
    //并发队列
    dispatch_queue_t concurrent = dispatch_queue_create("shifx", DISPATCH_QUEUE_CONCURRENT);
    NSLog(@"并发同步任务开始");
    dispatch_sync(concurrent, ^{
        sleep(1);
        for (int i = 0; i<3; i++) {
            NSLog(@"并发同步任务1 = %d",i);
        }
    });
    dispatch_sync(concurrent, ^{
        sleep(1);
        for (int i = 0; i<3; i++) {
            NSLog(@"并发同步任务2 = %d",i);
        }
    });
    NSLog(@"并发同步任务结束");
}

运行结果

从结果得知,并发队列执行的同步任务也是按照顺序依次执行的,因为它们都在主线程中执行的,没有开启新的线程。感兴趣的小伙伴可以打印下线程看下。

串行队列+异步执行

代码实现

-(void)serialAsysncText {
    //串行队列
    dispatch_queue_t serial = dispatch_queue_create("shifx", DISPATCH_QUEUE_SERIAL);
    NSLog(@"串行异步任务开始");
    dispatch_async(serial, ^{

        for (int i = 0; i<3; i++) {
            sleep(1);
            NSLog(@"串行异步任务1 = %d",i);
            NSLog(@"当前线程:%@",[NSThread currentThread]);
        }
    });
    dispatch_async(serial, ^{
        for (int i = 0; i<3; i++) {
            sleep(1);
            NSLog(@"串行异步任务2 = %d",i);
            NSLog(@"当前线程:%@",[NSThread currentThread]);
        }
    });
    NSLog(@"串行异步任务结束");
}

运行结果

从运行结果可以看出,

  • 所有的异步任务都是在打印串行异步任务结束后开始执行;
  • 开启了新的线程,但只开启了一个线程;
  • 在串行队列中的异步任务也是按照先后顺序执行。

并发队列+异步执行

代码实现

-(void)concurrentAsysncText {
    //并发队列
    dispatch_queue_t concurrent = dispatch_queue_create("shifx", DISPATCH_QUEUE_CONCURRENT);
    NSLog(@"并发异步任务开始");
    dispatch_async(concurrent, ^{
        for (int i = 0; i<3; i++) {
            sleep(1);
            NSLog(@"并发异步任务1 = %d",i);
            NSLog(@"当前线程:%@",[NSThread currentThread]);
        }
    });
    dispatch_async(concurrent, ^{

        for (int i = 0; i<3; i++) {
            sleep(1);
            NSLog(@"并发异步任务2 = %d",i);
            NSLog(@"当前线程:%@",[NSThread currentThread]);
        }
    });
    NSLog(@"并发异步任务结束");
}

运行结果

从运行结果来看,

  • 所有的异步任务都是在打印并发异步任务结束后开始执行;
  • 由于两个异步任务,并发队列开启了两个新的线程
  • 两个异步任务执行没有先后顺序

主队列 + 同步任务

在主线程调用主队列同步任务

由于主队列是串行队列,它不能在主线程中调用主队列同步任务,如下所示

崩溃原因就是同步任务放在了主线程中,需要等待主线程执行完毕才可以,而主线程需要等待该方法执行完成,两者互相等待造成死锁,所以崩溃了。

其他线程调用主队列同步任务

代码

//使用 NSThread 的 detachNewThreadWithBlock 方法会创建线程
[NSThread detachNewThreadWithBlock:^{
    [self mainSysncText];
}];

-(void)mainSysncText {
    NSLog(@"当前所在的线程:%@",[NSThread currentThread]);
    dispatch_sync(dispatch_get_main_queue(), ^{
        for (int i = 0; i<2; i++) {
            sleep(1);
            NSLog(@"主队列同步任务1 = %d",i);
            NSLog(@"当前线程:%@",[NSThread currentThread]);
        }
    });
    dispatch_sync(dispatch_get_main_queue(), ^{
        for (int i = 0; i<2; i++) {
            sleep(1);
            NSLog(@"主队列同步任务2 = %d",i);
            NSLog(@"当前线程:%@",[NSThread currentThread]);
        }
    });
}

执行结果

主队列+异步任务

由于主队列是串行队列,所以主队列+异步任务就相当于串行队列+异步任务

代码

-(void)mainAsysncText {
    NSLog(@"当前所在的线程:%@",[NSThread currentThread]);
    NSLog(@"主队列异步任务开始");
    dispatch_async(dispatch_get_main_queue(), ^{
        for (int i = 0; i<2; i++) {
            sleep(1);
            NSLog(@"主队列异步任务1 = %d",i);
            NSLog(@"当前线程:%@",[NSThread currentThread]);
        }
    });
    dispatch_async(dispatch_get_main_queue(), ^{
        for (int i = 0; i<2; i++) {
            sleep(1);
            NSLog(@"主队列异步任务2 = %d",i);
            NSLog(@"当前线程:%@",[NSThread currentThread]);
        }
    });
    NSLog(@"主队列异步任务结束");
}

运行结果

效果等同于串行队列+异步任务

作者:我是小菜
链接:https://juejin.im/post/6893877688990662664

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/henry_lei/article/details/109642032

智能推荐

JetBrain系列软件使用_afterlife_union的博客-程序员信息网

XSHELLfrom:https://jingyan.baidu.com/article/a378c960d19b13b3282830d2.html设置快速复制

Openstack Vmware虚拟机迁移到openstack_Icoding_F2014的博客-程序员信息网_ovf转换成openstack

实验环境是使用vmware搭建的centos 7虚拟机,生产环境需要换到openstack上跑虚拟机。首先, 在vmware里面导出虚拟机,导出格式为ovf这其实是一个压缩文件,把这个.ovf 用解压软件tar -xvf提取出其中的 CentOS7-disk1.vmdk 文件,并把这个文件上传到openstack服务器。使用qemu-img 工具把vmdk转换为qcow2格式...

【模型量化】——LSQ-Net: Learned Step Size Quantization论文_农夫山泉2号的博客-程序员信息网

亮点:ICLR2020论文:https://arxiv.org/pdf/1902.08153.pdfcode:非官方实现摘要在推理时以低精度操作运行的深层网络具有比高精度替代方案更强大的功耗和空间优势,但是需要克服随着精度降低而保持高精度的挑战。在这里,我们提出了一种用于训练此类网络的方法,即“学习步长量化”,该方法可以在使用模型时在ImageNet数据集上实现迄今为止最高的准确性。各种架构,权重和激活量化为2位,3位或4位精度,并且可以训练达到完全精度基准精度的3位模型。我们的方法建立在现有方.

UT005071: Undertow request failed HttpServerExchange{ GET /****}_zhou神的博客-程序员信息网

Caused by: java.lang.NoClassDefFoundError: Could not initialize class org.xnio.channels.Channels at io.undertow.servlet.spec.ServletOutputStreamImpl.flushInternal(ServletOutputStreamImpl.java:495) at io.undertow.servlet.spec.ServletOutputStreamImpl...

【BUUCTF】Web之[HCTF 2018]WarmUp 1_酥酥~的博客-程序员信息网

1、首先打开题目链接2、因为是php代码审计,所以我们尝试寻找代码。先查看网页源码 这里发现一个注释的php文件3、尝试对source.php进行访问4、出现了php代码,进行代码分析 ① 观察参数file,首先file不能为空,其次要满足是字符串类型 php if (! empty($_REQUEST['file']) &amp;&amp; is_string($_REQUEST['file']) &amp;&amp; emmm::checkFil.

Vue devtool的多种安装方式_独鹿DT的博客-程序员信息网_vue devtool

Vue devtools的安装两种方式,主要将第二种,略微记录第一种。第一种:通过Chrome网上应用店 进行Vue devtools的安装第二种:通过Github上 Vue devtools的代码进行安装Vue devtools 仓库地址先将其克隆到本地查看目录解构可知:使用 yarn进行包管理的。有 yarn的直接跳过下一步,没有的可以看下一步。安装yarn。全局安装npm install yarn -g 局部安装: npm install yarn -D演示使用局部安装的

随便推点

json比较_铽可喏的博客-程序员信息网_json 比较

 import jsondef isEqual(standard_dict, target_dict): if not standard_dict or not target_dict: if not standard_dict: print &quot;Not find standard semantic&quot; if not targe...

"->" 在c语言中是什么意思?_Motto6666的博客-程序员信息网_c语言中->

转载 https://blog.csdn.net/zhaojiabo1997/article/details/80286526-&gt; 在c语言中是什么意思?-&gt; 在c语言中是什么意思?检举**-&gt;**在C语言中称为间接引用运算符,是二目运算符,优先级同成员运算符“.”。用法:p-&gt;a,其中p是指向一个结构体的指针,a是这个结构体类型的一个成员。表达式p-&gt;a...

记录:Unknown custom element: [v-table] - did you register the component correctly...报错【亲测有效】_bug菌¹的博客-程序员信息网

记录:Unknown custom element: [v-table] - did you register the component correctly...报错。

突破程序员基本功的16课-3(Map,List)_weixin_33860737的博客-程序员信息网

2019独角兽企业重金招聘Python工程师标准&gt;&gt;&gt; ...

Pang-Blog开发-1:数据库设计_小胖儿emmm的博客-程序员信息网

概要数据库设计没有太严格的需求分析,也没有标准的E-R图,个人参考了一些大佬们的博客上的东西,然后自己总结了一个数据库。有关数据库我也没有过多的介绍的,下面还是直接贴注解和代码吧:数据库搭建用户表(唯一管理员)登陆账号登陆密码(加密)密码盐值昵称性别个人邮箱个人QQ个人电话个人头像(储存路径)个人生日访客表(记录访客的一些基本信息)访客IP(访客IP为主键)第一次访...

哈哈,对自己说生日快乐_weixin_33962923的博客-程序员信息网

今天10月23号,收到几个人的短信生日祝福还有电话没想到她还会给我打电话过来其实我的生日是阴历的10月23号,不是今天但是将错就错吧更正过来也没什么实际意义天气很好,我却不知道该做一些什么只好来到公司打开电脑上上网现在的目标是在过年以前攒钱买台电脑不知道这个目标可不可以实现呢?争取吧...

推荐文章

热门文章

相关标签