技巧理解GCD

作者: YW_Drenched | 来源:发表于2018-06-21 10:27 被阅读12次

之前对GCD的理解很浅,就是那种看了一会能勉强理解,可是过一段时间又给忘记了,又得回头来看。这次下定决心一定要把GCD给吃透了。网上也有很多不错关于GCD的文章帮助了我的理解。

很多情况下,我们使用GCD的情况基本是以下几种:

  • 异步获取网络数据,在主线程中刷新UI
    override func viewDidLoad() {
        super.viewDidLoad()
        loadData { (result) in
            // 获取到数据赋值
            self.dataArr = result
            //刷新tableView列表
            self.tableView.reloadData()
        }
        setupUI()  
    }
    
    func loadData(completion:@escaping (_ result:([String]))->()){
        DispatchQueue.global().async {
            print("模拟网络延迟")
            Thread.sleep(forTimeInterval: 3.0)
            let arr = ["😝","🤣","🙄","🌹","💰","😪","😴"]
            DispatchQueue.main.async {
                print("回到主线程,更新UI")
                completion(arr)
            }
        }
    }
  • 定时操作
func timer() {
        print("开始")
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 2.0) {
            print("结束")
        }
    }
  • 设计单例
static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        
    });

但往往形成了这种固有的套路以后,自己代码写着写着的时候回头看就很容易产生疑问,为什么要这样写?到底什么是队列?什么是任务?

任务:就是执行操作的意思,换句话说就是你在线程中执行的那段代码。而GCD中的任务只是一个代码块,它可以指一个block或者函数指针。执行任务有两种方式:同步执行(sync)和异步执行(async)。两者的主要区别是:是否等待队列的任务执行结束,以及是否具备开启新线程的能力。
  • 同步执行(sync):

    同步添加任务到指定的队列中,在添加的任务执行结束之前,会一直等待,直到队列里面的任务完成之后再继续执行。
    只能在当前线程中执行任务,不具备开启新线程的能力。

  • 异步执行(async):

    异步添加任务到指定的队列中,它不会做任何等待,可以继续执行任务。
    可以在新的线程中执行任务,具备开启新线程的能力。

队列(Dispatch Queue):这里的队列指执行任务的等待队列,即用来存放任务的队列。队列是一种特殊的线性表,采用 FIFO(先进先出)的原则,即新任务总是被插入到队列的末尾,而读取任务的时候总是从队列的头部开始读取。每读取一个任务,则从队列中释放一个任务。在 GCD 中有两种队列:串行队列和并发队列。两者都符合 FIFO(先进先出)的原则。两者的主要区别是:执行顺序不同,以及开启线程数不同。
  • 串行队列(Serial Dispatch Queue):

    每次只有一个任务被执行。让任务一个接着一个地执行。(只开启一个线程,一个任务执行完毕后,再执行下一个任务)

  • 并发队列(Concurrent Dispatch Queue):

    可以让多个任务并发(同时)执行。(可以开启多个线程,并且同时执行任务)

这以上对任务和队列的理解是源自这两篇很好的文章:
巧谈GCD
iOS多线程:『GCD』详尽总结

有了上面大神们对队列和任务的解释,现在对GCD也有了些许概念。在这个基础上,我来说说我的一个技巧理解GCD的方式。首先我们可以把任务看做是水滴,而队列就是管道了。串行队列的管道很细,只有容纳下一滴水的直径。而并发队列的管道的直径很粗,可以容纳下很多水滴。下面就具体到队列与任务之间的搭配了。

  • 同步+串行
    不会开启新线程,在当前线程执行任务。任务是串行的,执行完一个任务,再执行下一个任务。任务1,任务2依次执行


    同步+串行
  • 同步+并发
    在当前线程中执行任务,不会开启新线程,执行完一个任务,再执行下一个任务。因为是同步的任务,所以会等待任务1执行完,在执行任务2。同理,任务3也是等任务2执行完毕之后再开始执行


    同步+并发

同步任务是没有开辟线程的能力的

  • 异步+串行
    会开启新线程,但是因为任务是串行的,执行完一个任务,再执行下一个任务


    异步+串行
  • 异步+并发

    可以开启多个线程,任务交替(同时)执行。会并行执行多个任务,这也是我们最常用的一种方式。 异步+并发

异步任务是有开辟线程的能力的,但是在主队列中,异步就失去了这种能力

  • 同步+主队列
    在不同线程中调用结果也是不一样,在主线程中调用会出现死锁,而在其他线程中则不会。

  • 异步+主队列
    只在主线程中执行任务,执行完一个任务,再执行下一个任务。


    队列和任务组合的总结

另外在github上有OC版的demo,如有什么问题,欢迎大家补充
OC Demo

相关文章

  • 技巧理解GCD

    之前对GCD的理解很浅,就是那种看了一会能勉强理解,可是过一段时间又给忘记了,又得回头来看。这次下定决心一定要把G...

  • GCD相关知识点

    GCD相关知识点 多线程技术--GCD 深入学习GCD GCD 深入理解:第一部分 GCD 深入理解:第二部分 1...

  • GCD

    相关链接GCD使用经验与技巧浅谈

  • 多线程系列文章

    GCD基础篇 - 同步、异步,并发、并行的理解 GCD中级篇 - dispatch_group的理解及使用 dis...

  • 10.7 OC - 多线程的使用技巧

    多线程使用技巧(NSTheard/NSOperationQueue/GCD) NSTheard [NSThread...

  • GCD理解

    Dispatch Queues的生成可以有这几种方式: 1.dispatch_queue_tqueue=dispa...

  • 理解GCD

    (1)博客:深入理解GCD 理解iOS中的线程池 多线程理解 ?:(1)信号量--...

  • 面试问题总结

    Runtime理解。 Runloop理解,结合计时器。 GCD常用的方法。 GCD的原理。 KVO和KVC的实现原...

  • GCD 深入理解:第一部分

    GCD 深入理解:第一部分 什么是 GCD GCD 是 libdispatch 的市场名称,而 libdispat...

  • iOS笔记--GCD相关知识

    GCD相关知识 1.GCD(Grand Central Dispatch)教程 2.GCD 深入理解:第一部分 备...

网友评论

    本文标题:技巧理解GCD

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