- 項目開發(fā)過程中, 經(jīng)常遇到單個頁面需要發(fā)起多個網(wǎng)絡(luò)請求, 而且還需要控制執(zhí)行順序或者所有請求結(jié)束后統(tǒng)一處理數(shù)據(jù)的情況. 最明顯的解決方案就是嵌套,但是如果請求多了,代碼確實有點惡心
DispatchQueue
- 串行隊列的創(chuàng)建
let queue = DispatchQueue(label: "myQueue")
- 并行隊列的創(chuàng)建, 參數(shù)說明
- label: 隨意命名,隊列的標(biāo)識
- qos(服務(wù)質(zhì)量): DispatchQoS.default DispatchQoS.background(后臺執(zhí)行) DispatchQoS.unspecified(不指定) DispatchQoS.userInitiated(用戶發(fā)起) 等
- attributes: DispatchQueue.Attributes.concurrent(并行隊列) 不指定的情況是串行隊列
- autoreleaseFrequency(自動釋放的頻度): inherit(繼承) workItem(工作組) never(從不)
let queue = DispatchQueue(label: "myQueue", qos: DispatchQoS.default, attributes: DispatchQueue.Attributes.concurrent, autoreleaseFrequency: DispatchQueue.AutoreleaseFrequency.inherit, target: nil)
- 簡單使用
let queue = DispatchQueue(label: "myQueue", qos: DispatchQoS.default, attributes: DispatchQueue.Attributes.concurrent, autoreleaseFrequency: DispatchQueue.AutoreleaseFrequency.inherit, target: nil)
queue.async {
sleep(1)
print("in queue 111")
}
queue.async {
sleep(1)
print("in queue 222")
}
print("finish")

image
DispatchGroup(進入正題)
線程組有兩種模式, 阻塞式(DispatchGroup-wait) 和 非阻塞式(DispatchGroup-notify)
wait
workingGroup.enter() 和 workingGroup.leave() 要成對出現(xiàn), 只有l(wèi)eave()之后才會開始新的enter()
隊列中的請求任務(wù)是否順序執(zhí)行, 取決于自己創(chuàng)建的隊列類型
// DispatchGroup-wait(阻塞)
let workingGroup = DispatchGroup()
let workingQueue = DispatchQueue(label: "request_queue") // 這個是串行的隊列, queue里面的任務(wù)會順序執(zhí)行
//let workingQueue = DispatchQueue(label: "request_queue1", qos: DispatchQoS.default, attributes: DispatchQueue.Attributes.concurrent, autoreleaseFrequency: DispatchQueue.AutoreleaseFrequency.inherit, target: nil) // 這個是并行隊列, queue里面的任務(wù)會同時執(zhí)行
workingGroup.enter() // 開始
workingQueue.async {
Thread.sleep(forTimeInterval: 2)
print("接口 A 數(shù)據(jù)表請求完成")
workingGroup.leave() // 結(jié)束
}
workingGroup.enter() // 開始
workingQueue.async {
Thread.sleep(forTimeInterval: 1)
print("接口 B 數(shù)據(jù)表請求完成")
workingGroup.leave() // 結(jié)束
}
print("========= 我是最開始執(zhí)行的 =========")
workingGroup.wait() // 阻塞, 直到Group中的任務(wù)都結(jié)束
print("接口 A 和接口 B 的數(shù)據(jù)都已經(jīng)請求完畢, 開始合并兩個接口的數(shù)據(jù)")
print("========= 完美結(jié)束完美結(jié)束 =========")

image
notify
任務(wù)結(jié)束后, 通過通知回調(diào)的方式繼續(xù)執(zhí)行, 同時不會阻塞線程
// DispatchGroup-notify(不阻塞)
let workingGroup1 = DispatchGroup()
//let workingQueue1 = DispatchQueue(label: "request_queue1", qos: DispatchQoS.default, attributes: DispatchQueue.Attributes.concurrent, autoreleaseFrequency: DispatchQueue.AutoreleaseFrequency.inherit, target: nil) // 創(chuàng)建并行隊列
let workingQueue1 = DispatchQueue(label: "request_queue1") // 創(chuàng)建的默認(rèn)隊列是串行隊列
workingGroup1.enter()
workingQueue1.async {
Thread.sleep(forTimeInterval: 2)
print("接口 C 數(shù)據(jù)表請求完成")
workingGroup1.leave()
}
workingGroup1.enter()
workingQueue1.async {
Thread.sleep(forTimeInterval: 1)
print("接口 D 數(shù)據(jù)表請求完成")
workingGroup1.leave()
}
print("↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 我是最開始執(zhí)行的 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓")
workingGroup.notify(queue: workingQueue1) {
print("接口 C 和接口 D 的數(shù)據(jù)都已經(jīng)請求完畢, 開始合并兩個接口的數(shù)據(jù)")
}
print("驗證不阻塞 O(∩_∩)O哈哈~")

image
結(jié)束語
媽媽再也不用擔(dān)心我了
通過實際操作, 同時發(fā)起多個網(wǎng)絡(luò)請求, 發(fā)現(xiàn)以上的兩種方式, 只是控制了請求的順序, 并沒有控制返回數(shù)據(jù)的順序, 然后心態(tài)崩了, 只是崩了一小會兒, 繼續(xù)往下, 問題解決
swift中的信號量使用
// 創(chuàng)建初始值為0的信號量,這時代表是紅燈
let sema = DispatchSemaphore(value: 0)
// 讓信號量 -1,比如默認(rèn)值時0, wait()以后就變成了 -1了,因此會等待
sema.wait()
// 讓信號量 +1, 當(dāng)>0時就代表綠燈可以走了
sema.signal()
let workingGroup = DispatchGroup()
let workingQueue = DispatchQueue(label: "request_queue")
workingGroup.enter() // 開始
workingQueue.async {
let sema = DispatchSemaphore(value: 0)
let params = ["id": "458"]
self.req1(params, sema: sema)
sema.wait() // 等待任務(wù)結(jié)束, 否則一直阻塞
workingGroup.leave() // 結(jié)束
}
workingGroup.enter() // 開始
workingQueue.async {
let sema = DispatchSemaphore(value: 0)
self.req2(self.productId, sema: sema)
sema.wait() // 等待任務(wù)結(jié)束, 否則一直阻塞
workingGroup.leave() // 結(jié)束
}
workingGroup.notify(queue: DispatchQueue.main) {
// 全部調(diào)用完成后回到主線程,更新UI
}
private func req1(_ params: [String: Any], sema: DispatchSemaphore) {
LBProductNetManager.req_addOrApplyNow(params: params, success: { (result) in
// 信號量+1
sema.signal()
}) { (error) in
// 失敗的時候也要+1, 否則會永遠阻塞了
sema.signal()
}
}
private func req2(_ productId: Int, sema: DispatchSemaphore) {
LBProductNetManager.req_getHealthNotice(213, success: { (result) in
// 信號量+1
sema.signal()
}) { (error) in
// 失敗的時候也要+1, 否則會永遠阻塞了
sema.signal()
}
}
摘自 Chaos_G 本文僅作為學(xué)習(xí)使用 如有侵權(quán) 麻煩聯(lián)系我 立即刪除