參考文章:
1麸粮、Swift 3使用GCD和DispatchQueues
2、線程死鎖
基本概念:
串行隊(duì)列:只有一個(gè)線程镜廉,加入到隊(duì)列中的操作按添加順序依次執(zhí)行弄诲。并且還要保證在執(zhí)行某個(gè)任務(wù)時(shí),在它前面進(jìn)入隊(duì)列的所有任務(wù)肯定執(zhí)行完了娇唯。對(duì)于每一個(gè)不同的串行隊(duì)列齐遵,系統(tǒng)會(huì)為這個(gè)隊(duì)列建立唯一的線程來(lái)執(zhí)行代碼。
并發(fā)隊(duì)列:這個(gè)隊(duì)列中的任務(wù)也是按照先來(lái)后到的順序開(kāi)始執(zhí)行塔插,注意是開(kāi)始梗摇,但是它們的執(zhí)行結(jié)束時(shí)間是不確定的,取決于每個(gè)任務(wù)的耗時(shí)想许。對(duì)于n個(gè)并發(fā)隊(duì)列伶授,GCD不會(huì)創(chuàng)建對(duì)應(yīng)的n個(gè)線程而是進(jìn)行適當(dāng)?shù)膬?yōu)化
同步執(zhí)行:會(huì)阻塞當(dāng)前線程 sync默認(rèn)會(huì)在當(dāng)前線程執(zhí)行(系統(tǒng)優(yōu)化)
異步執(zhí)行:異步添加任務(wù)
1、主隊(duì)列和全局隊(duì)列
全局隊(duì)列(可以設(shè)置服務(wù)等級(jí)(Qos class))
DispatchQueue.global().async {
//主隊(duì)列
DispatchQueue.main.async {
}
}
ps:蘋(píng)果為了優(yōu)化性能, sync會(huì)盡可能在當(dāng)前線程來(lái)運(yùn)行
ps:主線程|當(dāng)前線程
print(Thread.main,Thread.current,Thread.isMainThread)
2流纹、隊(duì)列的優(yōu)先級(jí)
.userInteractive
.userInitiated
.default
.utility
.background
.unspecified
3糜烹、并發(fā)隊(duì)列(Concurrent Queues)
1、隊(duì)列默認(rèn)就是串行執(zhí)行的(serial)
//創(chuàng)建并行隊(duì)列
let anotherQueue = DispatchQueue(label:"com.appcoda.anotherQueue",qos:.utility,attributes: .concurrent)
2漱凝、通過(guò)定義為initiallyInactive
隊(duì)列任務(wù)不會(huì)自動(dòng)開(kāi)始執(zhí)行疮蹦,需要開(kāi)發(fā)者主動(dòng)去觸發(fā)
let anotherQueue2 = DispatchQueue(label:"com.appcoda.anotherQueue2",
qos: .utility,attributes[.concurrent,.initiallyInactive])
//手動(dòng)觸發(fā)
if let queue = inactiveQueue {
queue.activate()
}
PS:
//Suspend可以掛起一個(gè)線程,就是把這個(gè)線程暫停了茸炒,它占著資源愕乎,但不運(yùn)行阵苇,
//用Resume是繼續(xù)掛起的線程,讓這個(gè)線程繼續(xù)執(zhí)行下去
anotherQueue2.resume()
anotherQueue2.suspend(
4感论、延遲執(zhí)行
let delay = DispatchTime.now() + .seconds(60)
DispatchQueue.main. asyncAfter(when: delay) {
// Do something
}
OC的實(shí)現(xiàn)
let dispatch_time = dispatch_time(DISPATCH_TIME_NOW, Int64(60 * NSEC_PER_SEC))
/*
是當(dāng)前事前慎玖, 然后加上 .seconds(60) 代表 60秒。
再使用 DispatchQueue.main.after
讓這個(gè)操作在 60 秒后執(zhí)行
*/
DispatchTime.now()
5笛粘、DispatchWorkItem對(duì)象
let workItem = DispatchWorkItem {
//代碼塊
}
let queue = Dispatchqueue.global()
//默認(rèn)在主隊(duì)列執(zhí)行(下面是全局隊(duì)列執(zhí)行)
queue.async {
workItem.perform()
}
//執(zhí)行完成后通知
workItem.notify(queue: Dispatchqueue.main) {
}
6趁怔、DispatchGroup
隊(duì)列組
//創(chuàng)建 DispatchGroup
let group = DispatchGroup()
//添加隊(duì)列
group.enter()
let queue = DispatchQueue.global()
queue.async {
for _ in 0...100{
print("全局隊(duì)列")
}
//出隊(duì)列
group.leave()
}
//如果需要上個(gè)隊(duì)列完成后再執(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("隊(duì)列執(zhí)行完畢")
}
錯(cuò)誤分析
1、主線程調(diào)用 DispatchQueue.main.sync 同步隊(duì)列薪前,出現(xiàn)線程阻塞润努。
viewDidAppear方法的代碼相當(dāng)于mainQueue的一個(gè)任務(wù)(假設(shè)任務(wù)A), 現(xiàn)在它里面加了個(gè)sync的{假設(shè)任務(wù)B}, 意味著任務(wù)B只有等任務(wù)A完成才能開(kāi)始, 但是要完成任務(wù)A的話就必須先完成任務(wù)B,這樣相互等待出現(xiàn)線程阻塞示括。