參考文章:
1、Swift 3使用GCD和DispatchQueues
2、線程死鎖
基本概念:
串行隊列:只有一個線程,加入到隊列中的操作按添加順序依次執(zhí)行。并且還要保證在執(zhí)行某個任務時,在它前面進入隊列的所有任務肯定執(zhí)行完了。對于每一個不同的串行隊列,系統(tǒng)會為這個隊列建立唯一的線程來執(zhí)行代碼。
并發(fā)隊列:這個隊列中的任務也是按照先來后到的順序開始執(zhí)行,注意是開始,但是它們的執(zhí)行結(jié)束時間是不確定的,取決于每個任務的耗時。對于n個并發(fā)隊列,GCD不會創(chuàng)建對應的n個線程而是進行適當?shù)膬?yōu)化
同步執(zhí)行:會阻塞當前線程 sync默認會在當前線程執(zhí)行(系統(tǒng)優(yōu)化)
異步執(zhí)行:異步添加任務
1、主隊列和全局隊列
全局隊列(可以設置服務等級(Qos class))
DispatchQueue.global().async {
//主隊列
DispatchQueue.main.async {
}
}
ps:蘋果為了優(yōu)化性能, sync會盡可能在當前線程來運行
ps:主線程|當前線程
print(Thread.main,Thread.current,Thread.isMainThread)
2、隊列的優(yōu)先級
.userInteractive
.userInitiated
.default
.utility
.background
.unspecified
3、并發(fā)隊列(Concurrent Queues)
1、隊列默認就是串行執(zhí)行的(serial)
//創(chuàng)建并行隊列
let anotherQueue = DispatchQueue(label:"com.appcoda.anotherQueue",qos:.utility,attributes: .concurrent)
2、通過定義為initiallyInactive 隊列任務不會自動開始執(zhí)行,需要開發(fā)者主動去觸發(fā)
let anotherQueue2 = DispatchQueue(label:"com.appcoda.anotherQueue2",
qos: .utility,attributes[.concurrent,.initiallyInactive])
//手動觸發(fā)
if let queue = inactiveQueue {
queue.activate()
}
PS:
//Suspend可以掛起一個線程,就是把這個線程暫停了,它占著資源,但不運行,
//用Resume是繼續(xù)掛起的線程,讓這個線程繼續(xù)執(zhí)行下去
anotherQueue2.resume()
anotherQueue2.suspend(
4、延遲執(zhí)行
let delay = DispatchTime.now() + .seconds(60)
DispatchQueue.main. asyncAfter(when: delay) {
// Do something
}
OC的實現(xiàn)
let dispatch_time = dispatch_time(DISPATCH_TIME_NOW, Int64(60 * NSEC_PER_SEC))
/*
是當前事前, 然后加上 .seconds(60) 代表 60秒。
再使用 DispatchQueue.main.after
讓這個操作在 60 秒后執(zhí)行
*/
DispatchTime.now()
5、DispatchWorkItem對象
let workItem = DispatchWorkItem {
//代碼塊
}
let queue = Dispatchqueue.global()
//默認在主隊列執(zhí)行(下面是全局隊列執(zhí)行)
queue.async {
workItem.perform()
}
//執(zhí)行完成后通知
workItem.notify(queue: Dispatchqueue.main) {
}
6、DispatchGroup
隊列組
//創(chuàng)建 DispatchGroup
let group = DispatchGroup()
//添加隊列
group.enter()
let queue = DispatchQueue.global()
queue.async {
for _ in 0...100{
print("全局隊列")
}
//出隊列
group.leave()
}
//如果需要上個隊列完成后再執(zhí)行可以用wait
//group.wait()
group.enter()
let queue2 = DispatchQueue(label: "com.pingan.test", attributes: .concurrent)
queue2.sync {
for i in 0...10{
print("",i)
}
group.leave()
}
//全部執(zhí)行完畢后通知
group.notify(queue: DispatchQueue.main) {
print("隊列執(zhí)行完畢")
}
錯誤分析
1、主線程調(diào)用 DispatchQueue.main.sync 同步隊列,出現(xiàn)線程阻塞。

viewDidAppear方法的代碼相當于mainQueue的一個任務(假設任務A), 現(xiàn)在它里面加了個sync的{假設任務B}, 意味著任務B只有等任務A完成才能開始, 但是要完成任務A的話就必須先完成任務B,這樣相互等待出現(xiàn)線程阻塞。