Swift-GCD的基本使用(Swift 3.0)

2016-12-05 14:15

在 Swift 3.0 以后, GCD 的使用发生了很大的变化, 相比 Swift 2.0+ ,变得更加简洁了!

首先学习几个比较重要的概念:

队列

  • 1 - 并发队列

  • 可以让多个任务并发(同时)执行(自动开启多个线程同时执行任务)
  • 并发功能只有在异步函数下才有效
  • 2 - 串行队列

  • 让任务一个接着一个地执行(一个任务执行完毕后,再执行下一个任务)
  • 同步和异步的区别

  • 同步:只能在当前线程中执行任务,不具备开启新线程的能力
  • 异步:可以在新的线程中执行任务,具备开启新线程的能力
  • Qos(Quality Of Service) 等同于OC中GCD 的优先级

    高 –> 低

  • userInteractive
  • userInitiated
  • default
  • utility
  • background
  • unspecified
  • GCD线程队列的创建方法

    1、创建一个串行队列

    let serialQueue = DispatchQueue(label: "Mazy", attributes: .init(rawValue: 0))

    2、创建一个并发队列

    let conQueue = DispatchQueue(label: "Mazy", attributes: .concurrent)

    3、获得全局并发队列

    let globalQueue = DispatchQueue.global()

    4、获得主队列

    let mainQueue = DispatchQueue.main

    同步/异步 + 串行/并发队列的组合

    1、同步 + 串行队列

    // 同步 + 串行队列:不会开启新的线程,在当前线程执行任务。任务是串行的,执行完一个任务,再执行下一个任务
    func sync_serial() {
           // 1、创建一个串行队列
           let serialQueue = DispatchQueue(label: "Mazy", attributes: .init(rawValue: 0))
           // 同步执行三个任务
           serialQueue.sync {
               print("1 + \(Thread.current)")
           }
           serialQueue.sync {
               print("2 + \(Thread.current)")
           }
           serialQueue.sync {
               print("3 + \(Thread.current)")
           }
       }

    打印结果:
    这里写图片描述

    总结:没有创建新线程,主线程执行任务,任务串行执行

    2、异步 + 串行队列

    // 异步 + 串行队列:开启新的线程,但只开启一条
    func async_serial() {
            // 1、创建一个串行队列
            let serialQueue = DispatchQueue(label: "Mazy", attributes: .init(rawValue: 0))
            // 异步执行三个任务
            serialQueue.async {
                print("1 + \(Thread.current)")
            }
            serialQueue.async {
                print("2 + \(Thread.current)")
            }
            serialQueue.async {
                print("3 + \(Thread.current)")
            }
        }

    打印结果:
    这里写图片描述
    总结:开启了一条线程,任务串行执行

    3、同步 + 并发队列

    // 同步 + 并发队列:不会开启新的线程
    func sync_concurrent() {
            // 创建一个全局
            let globalQueue = DispatchQueue.global()
            // 同步执行三个任务
            globalQueue.sync { 
                print("1 + \(Thread.current)")
            }
            globalQueue.sync {
                print("2 + \(Thread.current)")
            }
            globalQueue.sync {
                print("3 + \(Thread.current)")
            }
    
        }
    }

    打印结果:
    这里写图片描述
    总结:不开启新线程,主线程执行任务,任务也是顺序执行

    4、异步 + 并发队列

    // 异步 + 并发队列:同时开启多条线程
    func async_concurrent() {
    
            // 创建一个全局队列
            let globalQueue = DispatchQueue.global()
            // 异步执行三个任务
            globalQueue.async {
                print("1 + \(Thread.current)")
            }
            globalQueue.async {
                print("2 + \(Thread.current)")
            }
            globalQueue.async {
                print("3 + \(Thread.current)")
            }
        }

    打印结果:
    这里写图片描述
    总结:开启多条线程,并发执行任务

    GCD线程之间的通信

    从子线程回到主线程

    DispatchQueue.global().async {
                // 执行耗时的异步操作...
                DispatchQueue.main.async {
                    // 回到主线程,执行UI刷新操作
                }
            }

    线程之间的通信具体实现实例

        var imageView: UIImageView?
    
        func queuesCommunication() {
            // 创建 异步 全局并发队列
            DispatchQueue.global().async {
                // 图片的网络路径
                let url = URL(string: "http://xxx.jpg")
    
                if let u = url {
                    // Call can throw, but it is not marked with 'try' and the error is not handled
                    do {
                        // 加载图片
                        let data = try Data(contentsOf: u)
                        // 生成图片
                        let image = UIImage(data: data)
                        // 回到主线程设置图片
                        DispatchQueue.main.async {
                            self.imageView?.image = image
                        }
                    } catch { }
                }
            }

    GCD的其他使用

    延迟执行

    print("开始执行 \(NSDate())")
            let additionalTime: DispatchTimeInterval = .seconds(3)
            DispatchQueue.main.asyncAfter(deadline: .now() + additionalTime, execute: {
                print("3秒后执行 \(NSDate())")
            })

    执行结果
    这里写图片描述

    其他延迟执行方法

    // method 1
    perform(#selector(demo), with: nil, afterDelay: 3.0)
    
    // method 2
    Timer.scheduledTimer(withTimeInterval: 3.0, repeats: false, block: {_ in
     print("延迟3s执行")
    })
    

    创建线程群组
    例如同一个文件分段下载,待所有分段任务下载完成后,合并任务

    ```
    func group() {
            // 获得全局队列
            let globalQueue = DispatchQueue.global()
    
            // 创建一个队列组
            let group = DispatchGroup()
    
            globalQueue.async(group: group, execute: {
                print("任务一 \(Thread.current)")
            })
            globalQueue.async(group: group, execute: {
                print("任务二 \(Thread.current)")
            })
    
            // group内的任务完成后,执行此方法
            group.notify(queue: globalQueue, execute: {
                print("终极任务 \(Thread.current)")
            })
    
            globalQueue.async(group: group, execute: {
                print("任务三 \(Thread.current)")
            })
    
            globalQueue.async(group: group, execute: {
                print("任务四 \(Thread.current)")
            })
        }

    打印结果:
    这里写图片描述
    总结:开启多条线程,去执行群组中的任务,当群组内的四个任务执行完毕后,再去执行notify里面的任务

    注意:使用sync同步函数往当前串行队列中添加任务,会卡住当前的串行队列