zoukankan      html  css  js  c++  java
  • iOS多线程之4.GCD简介

    GCD(Grand Central Dispatch)应该是我们开发中最常用到的多线程解决方案,是苹果公司专门为多核的并行运算提出的解决方案,是基于C语言的,提供了很多非常强大的函数。

    GCD的优势

    1.会自动利用更多的CPU内核(从iPhone4s开始是双核,iPhone7系列是4核)。
    2.会自动管理线程的创建、生命周期、销毁等,不需要写一句关于线程的代码。
    3.将任务添加到队列中,GCD会自动从队列中将任务取出,放到对应的线程中执行。

    进程与线程

    1.简单点说一个APP就是一个进程,例如微信、迅雷都分别是一个进程。
    2.一个进程可以拥有多条线程。当我们打开APP时系统会自动帮我们创建一条主线程,当我们要让APP干点别的事时,例如刷新数据,就要开启一条子线程来向服务器请求数据,所以一个进程可以拥有多条线程。(并不是让APP干什么事,都会开启子线程,这里只是为了解释方便,才这么说的。)
    20161029092719352.png

    队列(queue)

    队列就是用来存放任务的,任务就是我们让APP干的事,例如下载图片,刷新数据等,都是任务。我们使用GCD,只要把任务放到队列中就可以了,系统会自动帮我们创建线程,调度任务。任务的调度原则遵行FIFO原则,就是哪个任务先放进队列中,就先执行。队列分为串行队列,和并行(并发)队列。
    1.串行队列 : 就是队列里的任务必须一个一个往下执行。例如我们要执行A、B、C 三个任务,我们把这三个任务放到串行队列中,必须是A执行完,B才执行,B执行完C才执行。
    创建串行队列有两种方法:
    (1)自定义队列
    代码:

     // 创建串行队列
        dispatch_queue_t queue = dispatch_queue_create("doujiangyoutiao", DISPATCH_QUEUE_SERIAL);
        // 添加任务A
        dispatch_async(queue, ^{
            NSLog(@"执行任务A");
        });
        // 添加任务B
        dispatch_async(queue, ^{
            NSLog(@"执行任务B");
        });
        // 添加任务C
        dispatch_async(queue, ^{
            NSLog(@"执行任务C");
        });
    

    日志

    2016-11-04 14:00:06.546 TTTTTTTTTT[11059:128030] 执行任务A
    2016-11-04 14:00:06.546 TTTTTTTTTT[11059:128030] 执行任务B
    2016-11-04 14:00:06.547 TTTTTTTTTT[11059:128030] 执行任务C
    

    1)“doujiangyoutiao”是这个队列的名字;
    2)DISPATCH_QUEUE_SERIAL表示创建的是一条串行对列。
    (2)主队列
    dispatch_queue_t queue =dispatch_get_main_queue();
    得到主队列,主队列是串行队列,主队列中的任务默认都在主线程中执行。
    2.并行队列:就是队列里的任务可以一齐执行。还是举执行A、B、C 三个任务的例子。我们把三个任务放到并行队列中,这三个任务可以一起执行,所以不一定谁先下载完。串行队列里一定是A先下载完。
    代码:

    - (void)viewDidLoad {
        [super viewDidLoad];
        
        // 创建并行队列
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        // 添加任务A
        dispatch_async(queue, ^{
            NSLog(@"执行任务A");
        });
        // 添加任务B
        dispatch_async(queue, ^{
            NSLog(@"执行任务B");
        });
        // 添加任务C
        dispatch_async(queue, ^{
            NSLog(@"执行任务C");
        });
    }
    

    每次打印的日志应该都不一样,有兴趣可以多试几次。

    2016-11-04 14:09:03.871 TTTTTTTTTT[11356:131391] 执行任务B
    2016-11-04 14:09:03.871 TTTTTTTTTT[11356:131393] 执行任务C
    2016-11-04 14:09:03.871 TTTTTTTTTT[11356:131390] 执行任务A
    

    创建并行队列有两种方法:
    (1)看上面代码得到全局并行队列,不需要我们创建,我们一般用这个。第一个参数表示这个队列的优先级
    (DISPATCH_QUEUE_PRIORITY_HIGH、DISPATCH_QUEUE_PRIORITY_DEFAULT、DISPATCH_QUEUE_PRIORITY_LOW、DISPATCH_QUEUE_PRIORITY_BACKGROUND),用第二个就可以。第二个参数还没开发出来,没有用,默认写0即可。
    (2)自定义队列
    dispatch_queue_t queue=dispatch_queue_create("fuhang",DISPATCH_QUEUE_CONCURRENT);
    "fuhang"为并发队列的名字,后面表示创建的队列为并行队列。

    注意:

    1. 并发队列里的任务一定会一起执行嘛?
      答:肯定不会啊。如果并发队列里有100个任务,一起执行就得创建100条线程,那不得累死CPU啊!任务少了会一起执行,任务多了对先一起执行一部分。
    2. 线程并发???
      答:错。串行并发是形容队列的!!!线程没有,线程里的任务都是一个一个的往下执行,不可能多个任务一起执行。

    同步和异步

    同步:会堵塞当前线程,队列里的任务执行完,任务所在的线程才会往下执行。其实说白了就是插队。
    dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
    第一个参数是队列,第二个参数是要往队列里添加的任务。

    20161029093326640.png
      异步:不会堵塞当前线程。
    dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
    同上。
      同步和异步就是用来判断是否要在当前线程的基础上创建新的线程。同步不会创建新的线程,队列里的任务在当前线程中执行,所以会堵塞当前线程。但是异步也不是一定会创建新的线程,这要根据CPU的使用情况来看,但是大多数情况会创建一个线程。

  • 相关阅读:
    【Azure 应用服务】在Azure App Service多实例的情况下,如何在应用中通过代码获取到实例名(Instance ID)呢?
    【Azure 应用服务】App Service For Windows 中如何设置代理实现前端静态文件和后端Java Spring Boot Jar包
    【Azure Developer】使用Azure Key Vault 的Key签名后,离线验证的一些参考资料
    【Azure Function】调试 VS Code Javascript Function本地不能运行,报错 Value cannot be null. (Parameter 'provider')问题
    【Azure 应用服务】App Service 使用Tomcat运行Java应用,如何设置前端网页缓存的相应参数呢(Xms512m Xmx1204m)?
    【Azure API 管理】APIM添加Logtoeventhub的策略后,一些相关APIM与Event Hub的问题
    【Azure API 管理】为调用APIM的请求启用Trace 调试APIM Policy的利器
    【Azure 事件中心】China Azure上是否有Kafka服务简答
    【Azure 应用服务】探索在Azure上设置禁止任何人访问App Service的默认域名(Default URL)
    【Azure 微服务】记一次错误的更新Service Fabric 证书而引发的集群崩溃而只能重建
  • 原文地址:https://www.cnblogs.com/doujiangyoutiao/p/6030150.html
Copyright © 2011-2022 走看看