目的
探究主队列和主线程关系。
过程
1.主队列任务是否一定在主线程执行?
DispatchQueue.global().async {
DispatchQueue.main.async {
let currentThread = Thread.current
print(currentThread.isMainThread) //打印为true
}
}
结论:所以主队列只会在主线程中执行。
2.主线程是否只执行主队列的任务?
DispatchQueue.global().sync {
let currentThread = Thread.current
print(currentThread.isMainThread) //打印为true
}
结论:主线程还有可能会执行其他队列的任务。这是为了避免线程切换对性能的消耗。因为CPU的寄存器只有一套,多线程执行时系统势必会不断调度切换。这样每个线程需要一个上下文来记录当前执行状态。这样新线程被执行时首先将上下文写入寄存器,执行结束寄存器重新写入上下文,如此不断切换才避免了多线程的数据混乱。
使用
RxSwift的判断方式:
extension DispatchQueue {
private static var token: DispatchSpecificKey<()> = {
let key = DispatchSpecificKey<()>()
DispatchQueue.main.setSpecific(key: key, value: ())
return key
}()
static var isMain: Bool {
return DispatchQueue.getSpecific(key: token) != nil
}
}
Kingfisher中为了提高性能当在主队列主线程中时就直接执行block。因为如果只判断是主队列就执行有可能此时CPU正在处理其他线程任务,如果只判断主线程那么此时执行的任务有可能是其他队列的,并不能保证block添加到执行的队列。
extension DispatchQueue {
// This method will dispatch the `block` to self.
// If `self` is the main queue, and current thread is main thread, the block
// will be invoked immediately instead of being dispatched.
func safeAsync(_ block: @escaping ()->()) {
if self === DispatchQueue.main && Thread.isMainThread {
block()
} else {
async { block() }
}
}
}