GCD, operating at the system level, can better accommodate the needs of all running applications, matching them to the available system resources in a balanced fashion.
文档中介绍,GCD是系统层面上的API,能够协调所有正在运行的APP所使用的资源,在iOS中,Apple是推荐大家使用GCD来进行多线程开发。
DispatchQueue
An object that manages the execution of tasks serially or concurrently on your app's main thread or on a background thread.
DispatchQueue是GCD中的一个类,常用于异步执行任务。
主队列与全局队列用法
// 主队列为串行队列,任务在主线程中执行
let mainQueue = DispatchQueue.main
// 全局队列为并行队列,任务在子线程中执行
let globalQueue = DispatchQueue.global()
// 主队列添加异步任务,任务在主线程执行
mainQueue.async {
print(Thread.current) // <NSThread: 0x6000020c0280>{number = 1, name = main}
}
// 全局队列添加异步任务,任务在子线程执行
globalQueue.async {
print(Thread.current) // <NSThread: 0x600002063a40>{number = 13, name = (null)}
}
串行队列与并行队列用法
// 自定义串行队列
let serialQueue = DispatchQueue(label: "com.serial")
// 自定义并行队列
let concurrentQueue = DispatchQueue(label: "com.concurrent", attributes: .concurrent)
for i in 0..<5 {
// 串行队列异步任务,在子线程中依次执行
serialQueue.async {
print(Thread.current) // <NSThread: 0x6000023c9800>{number = 5, name = (null)}
print(i) // 0 1 2 3 4 5
}
// 并行队列异步任务,在多个子线程中同时执行
concurrentQueue.async {
// 2 0 3 1 4
print(i)
// <NSThread: 0x600001007b00>{number = 7, name = (null)}
// <NSThread: 0x6000010017c0>{number = 6, name = (null)}
// <NSThread: 0x60000101ccc0>{number = 8, name = (null)}
// <NSThread: 0x60000100fa00>{number = 3, name = (null)}
// <NSThread: 0x600001007b00>{number = 7, name = (null)}
print(Thread.current)
}
}
同步任务与死锁
// 主队列为串行队列,任务在主线程中执行
let mainQueue = DispatchQueue.main
// 全局队列为并行队列,任务在子线程中执行
let globalQueue = DispatchQueue.global()
globalQueue.async {
print(Thread.current) // <NSThread: 0x60000100fa00>{number = 3, name = (null)}
globalQueue.sync {
// 在当前线程执行同步任务
print(Thread.current) // <NSThread: 0x60000100fa00>{number = 3, name = (null)}
}
}
globalQueue.async {
print(Thread.current) // <NSThread: 0x60000100fa00>{number = 3, name = (null)}
mainQueue.sync {
// 主队列的任务除外
// 主队列的同步/异步任务都在主线程上执行
print(Thread.current) // <NSThread: 0x600001e1cec0>{number = 1, name = main}
}
}
// 同步任务容易造成死锁
// 在主线程中往主队列中添加同步任务,造成死锁
mainQueue.sync {
print(Thread.current) // 死锁,App会崩溃
}
// 在子线程中往执行当前任务的串行队列中添加同步任务,造成死锁
serialQueue.async {
serialQueue.sync {
print(Thread.current) // 死锁,App会崩溃
}
}
DispatchGroup
A group of tasks that you monitor as a single unit.
从文档的描述中,我们可以猜测,DispatchGroup的作用,就是把多个任务统一成一个任务来完成,一起来看看具体的用法。
let group = DispatchGroup()
let queue = DispatchQueue(label: "com.concurrent", qos: .background, attributes: .concurrent)
for i in 0..<5 {
group.enter()
queue.async {
group.leave()
print(i)
}
}
// 阻塞当前线程,等待queue中的任务完成
group.wait()
// 不阻塞当前线程,当queue中任务完成时,接收通知
group.notify(qos: .default, flags: [], queue: queue) {
// do something
}
接下来
我们常常在子线程执行耗时操作,然后切换到主线程来更新UI,
DispatchQueue.global().async {
// do something time-consuming
DispatchQueue.main.async {
// update UI
}
}
我很好奇这个queue究竟是什么?子线程、主线程是从哪里来的?GCD中的主队列、全局队列,队列的并行、串行,任务的同步、异步究竟是如何实现的? 在下一篇文章中,我们先来看看队列是如何创建的。