技巧理解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

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