在 Swift 3.0 以后, GCD 的使用发生了很大的变化, 相比 Swift 2.0+ ,变得更加简洁了!
首先学习几个比较重要的概念:
1 - 并发队列
2 - 串行队列
高 –> 低
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)")
}
}
从子线程回到主线程
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 { }
}
}
延迟执行
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里面的任务