目的
探究主佇列和主執行緒關係。
過程
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() }
}
}
}
複製程式碼