在開發(fā)過程中,都會同服務(wù)器進(jìn)行交互,獲取數(shù)據(jù)上傳資源等。
在并發(fā)請求時,往往都只需要最終的一個結(jié)果。
比如,request請求 A,和請求 B, 我只需要知道最終 A 和 B 的執(zhí)行結(jié)果。
- 第一種辦法
用DispatchGroup
、leave()
和enter()
方法,
let group = DispatchGroup()
在開始請求 A 時,group.enter()
使信號量+1,在回調(diào)結(jié)果中group.leave()
-1,當(dāng)最終信號量平衡為0
時,會執(zhí)行group.notify(queue: DispatchQueue.global()) {}
中的 block,但是,請注意,如果 leave 和 enter不守恒,會造成內(nèi)存泄漏
。
代碼如下
for request in netWorkRequests {
DispatchQueue.global().async(group: group, execute: {
group.enter() //+1
//模擬網(wǎng)絡(luò)請求回調(diào) block,因為網(wǎng)絡(luò)請求也是會異步請求
DispatchQueue.global().async(execute: {
group.leave() //-1
})
print("\(Date()) --> 結(jié)束 %d==%@",image, Thread.current)
})
}
group.notify(queue: DispatchQueue.global()) {
print("\(Date()) --> 任務(wù)完成通知任務(wù)組")
}
這種做法簡單,只需要 enter、leave 就可以了,但是這樣的弊端就是:
一旦沒有執(zhí)行到 group.leave ,沒有-1,那么通知永遠(yuǎn)也不會執(zhí)行到,也就會造成內(nèi)存泄漏
。
- 第二種辦法
信號量DispatchSemaphore
let group = DispatchGroup()
let semaphore = DispatchSemaphore(value: 0)
for request in netWorkRequests {
DispatchQueue.global().async(group: group, execute: {
group.enter() //+1
//模擬網(wǎng)絡(luò)請求回調(diào) block,因為網(wǎng)絡(luò)請求也是會異步請求
DispatchQueue.global().async(execute: {
group.leave() //-1
})
print("\(Date()) --> 結(jié)束 %d==%@",image, Thread.current)
})
}
group.notify(queue: DispatchQueue.global()) {
print("\(Date()) --> 任務(wù)完成通知任務(wù)組")
}
//并發(fā)執(zhí)行之后通知結(jié)果
group.notify(queue: DispatchQueue.global()) {
for (i, _) in images.enumerated() where i>0{
semaphore.wait(timeout: DispatchTime.now()+DispatchTimeInterval.seconds(2*(images.count-(i+1))))
}
print("\(Date()) --> 任務(wù)完成通知任務(wù)組")
}
//如果信號量為0,則等待執(zhí)行 semaphore.signal(),如果在 timeout 時間范圍內(nèi)沒有 signal,依然會繼續(xù)執(zhí)行接下來的代碼
semaphore.wait(timeout: DispatchTime.now()+DispatchTimeInterval.seconds(2*images.count))