当前位置:   article > 正文

Swift-GCD的基本使用(Swift 3.0)_swift 任务一执行完毕在执行任务二

swift 任务一执行完毕在执行任务二

在 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))
  • 1

2、创建一个并发队列

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

3、获得全局并发队列

let globalQueue = DispatchQueue.global()
  • 1

4、获得主队列

let mainQueue = DispatchQueue.main
  • 1

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

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)")
       }
   }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

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

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


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)")
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

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


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)")
        }

    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

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


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)")
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

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


GCD线程之间的通信

从子线程回到主线程

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

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

    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 { }
            }
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

GCD的其他使用

延迟执行

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

执行结果
这里写图片描述


其他延迟执行方法

// method 1
perform(#selector(demo), with: nil, afterDelay: 3.0)

// method 2
Timer.scheduledTimer(withTimeInterval: 3.0, repeats: false, block: {_ in
     print("延迟3s执行")
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

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

```
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)")
        })
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

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


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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/691516
推荐阅读
相关标签
  

闽ICP备14008679号