美文网首页
多线程编程GCD

多线程编程GCD

作者: 绍清_shao | 来源:发表于2018-03-30 09:11 被阅读21次

1. 什么是GCD

异步执行任务的技术之一
在GCD之前,cocoa框架提供了NSObject类performSelectorInBackground:withObject实例方法和performSelectorOnMainThread实例方法

2. 什么是dispatch_sync和dispatch_async

dispatch_sync函数的“sync”意味着“非同步”,就是将指定的Block“非同步”追加到Dispatch Queue中。dispatch_sync函数不做任何等待。

dispatch_async函数的“async”意味着“同步”,就是将指定的Block“同步”追加到Dispatch Queue中。在追加Block结束之前,dispatch_sync函数会一直等待。等待意味着执行此Block的线程停止了。

3. 什么是Dispatch Queue

执行处理时存在两种Dispatch Queue,

  • 一种是等待现在执行中处理的Serial Dispatch Queue
    缺点:
    (1)过多使用多线程(生成大量的Serial Dispatch Queue),会消耗大量内存,引起大量的上下文切换,大幅度降低系统的响应性能。
    (2)多个Serial Dispatch Queue会发生数据竞争
  • 另外一种是不等待现在执行中处理的Concurrent Dispatch Queue
    注意:
    当想并发执行而不发生数据竞争和使用过多线程而导致性能等问题时使用Concurrent Dispatch Queue。

4. 如何创建Dispatch Queue

  1. 第一种方法是通过GCD的API生成Dispatch Queue
    dispatch_queue_create(<#const char * _Nullable label#>, <#dispatch_queue_attr_t _Nullable attr#>)
    第一个参数指定Queue名称
    推荐使用应用程序ID这种逆序全程域名。该名称在Xcode和Instrument的调试器中作为Dispatch Queue名称表示,也会出现在应用程序崩溃时所生成的CrashLog中
    第二个参数创建Dispatch Queue的类型
    如果指定为NULL,创建的是Serial Dispatch Queue。要生成Concurrent Dispatch Queue时要指定为DISPATCH_QUEUE_CONCURRENT

  2. 第二种方法是获取系统标准提供的Dispatch Queue
    Main Dispatch Queue
    正如其名称含有"Main"一样,是在主线程中执行的Dispatch Queue。因为主线程只有一个,所以Main Dispatch Queue自然就是Serial Dispatch Queue。
    Global Dispatch Queue
    所有应用程序都能使用的Concurrent Dispatch Queue,没有必要通过dispatch_queue_create函数逐个生成。
    另外Global Dispatch Queue有4个执行优先级,分别是高优先级(High Priority)、默认优先级(Default Priority)、低优先级(low Priority)、后台优先级(background Priority)。在向Global Dispatch Queue追加处理时,应选择与处理内容对应的执行优先级的Global Dispatch Queue。
    获取方法

    /*
     *  Main Dispatch Queue获取方法
     */
    dispatch_queue_t myConcurrentQueue =
    dispatch_get_main_queue();

    /*
     *  Global Dispatch Queue (高优先级) 的获取方法
     */
    dispatch_queue_t    globalDispatchQueueHige =
    dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);

    /*
     *  Global Dispatch Queue (默认优先级) 的获取方法
     */
    dispatch_queue_t    globalDispatchQueueDefalut =
    dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    /*
     *  Global Dispatch Queue (低优先级) 的获取方法
     */
    dispatch_queue_t    globalDispatchQueuelow =
    dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);
    /*
     *  Global Dispatch Queue (后台优先级) 的获取方法
     */
    dispatch_queue_t    globalDispatchQueuebackground =
    dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);

5. dispatch_after指定时间后执行处理

这里的时间可以是相对时间,例如3秒后执行,也可以是绝对时间,例如指定2100年11月11日11时这一绝对时间,可以作为粗略闹钟功能使用。
注意
dispatch_after函数并不是在指定时间后执行处理(block),而是指定时候后追加处理到Dispatch Queue中。如果线程本身有大量处理要追加,这个时间延长越厉害。
例子:

// 相对时间
  dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 3ull * NSEC_PER_SEC);
  dispatch_after(time, dispatch_get_main_queue(), ^{
        NSLog(@"3 秒后 执行这个");
    });
// 绝对时间
//5秒后的时间,可以指定任意绝对时间,例子里只是简单指定比现在晚5秒。
    NSDate *furtureDate = [[NSDate alloc] initWithTimeIntervalSinceNow:5];
    dispatch_time_t relTime = getDispatchTimeByDate(furtureDate);
    dispatch_after(relTime, dispatch_get_main_queue(), ^{
        NSLog(@"5 秒后 执行这个");
    });

注意:dispatch_walltime函数由POSIX中使用的struct timespec类型
的时间得到dispatch_time_t类型的值。具体装换如下:

dispatch_time_t getDispatchTimeByDate(NSDate *date) {
    NSTimeInterval interval;
    double second, subsecond;
    struct timespec time;
    dispatch_time_t milestone;
    
    interval = [date timeIntervalSince1970];
    subsecond = modf(interval, &second);
    time.tv_sec = second;
    time.tv_nsec = subsecond * NSEC_PER_SEC;
    milestone = dispatch_walltime(&time, 0);
    
    return milestone;
}

dispatch_after(dispatch_time_t when, dispatch_queue_t _Nonnull queue, ^(void)block)
第一个参数是指定时间dispatch_time_t。该值使用dispatch_time函数或者dispatch_walltime生成。
第二个参数指定要追加的Dispatch Queue。
最后一个参数要执行处理的Block。

6. Dispatch Group

使用场景是在追加到Dispatch Queue中多个处理全部结束后想执行结束处理。

Dispatch Group

7. dispatch_barrier_queue

使用场景:文件的读取与写入,为了避免发生数据竞争,多个文件的读取操做可以并行执行,但不可以与文件的写入操作并行,文件的写入操作之间只能串行且不能有文件读取操作存在。dispatch_barrier_async函数可以实现高效率的数据库访问和文件访问

dispatch_barrier_queue

相关文章

  • 多线程编程4 - GCD

    原文: 多线程编程4 - GCD 一、简介在iOS所有实现多线程的方案中,GCD应该是最有魅力的,因为GCD本身是...

  • 线程

    iOS 多线程:『GCD』详尽总结 NSThread详解 IOS 多线程编程 『NSOperation、NSOpe...

  • FLAnimatedImageView加载卡顿问题。

    GCD 的调用 转载“iOS多线程编程之Grand Central Dispatch(GCD)介绍和使用”

  • 知其然亦知其所以然-NSOperation并发编程

    对于iOS的并发编程, 用的最普遍的就是GCD了, GCD结合Block可以so easy的实现多线程并发编程. ...

  • iOS开发进阶-GCD

    什么是GCD GCD是大家现在常用的一种多线程编程技术之一,GCD用非常简洁的记述方法,实现了极为复杂繁琐的多线程...

  • ***线程,GCD,runloop(2)

    第三篇:多线程编程的多种方式 iOS执行多线程编程常用的有以下几种方式 NSThread GCD NSOperat...

  • GCD 多线程编程 - iOS开发

    前言 通过本文章你会学到: 多线程编程当中的基本概念 如何防止GCD多线程的读写问题 简介 GCD是Grand C...

  • iOS基础篇-GCD死锁

    GCD死锁概念: 使用GCD多线程编程时,如果同步函数dispatch_sync(),目标queue为当前queu...

  • iOS GCD基本用法

    iOS编程中运用最多的多线程就是GCD和NSOperation,NSOperation是苹果对GCD的OC封装,更...

  • 多线程之第三种编程方法GCD

    今天将介绍多线程GCD的编程方法:1、什么是GCD? 全称是Grand Central Dispatch,纯C语言...

网友评论

      本文标题:多线程编程GCD

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