多个网络请求做同步异步 解决方案
2019-07-30 本文已影响0人
山已几孑
需求: 根据文章id获取每个id下的附件列表,再根据附件列表下载附件。
简单考虑了几种方案,分别用GCD(串行),OperationQueue(串行+并行) 实现,可能想得太简单了,有问题欢迎打脸
GCD(DispatchSemaphore)
let semaphore = DispatchSemaphore(value: 0)
for i in 0...2 {
DispatchQueue.global().async {
sleep(2)
print("🍠模拟第一层请求 回调")
let semaphore2 = DispatchSemaphore(value: 0) //第二个信号量,控制里面都执行完
for _ in 0...2 {
let queue = DispatchQueue(label: "ConcurrentQueue\(i)", qos: .userInteractive, attributes: DispatchQueue.Attributes.concurrent)
queue.async {
sleep(1)
print("☀️模拟一个异步请求下载---\(Date(timeIntervalSinceNow: 0))")
semaphore2.signal()
}
semaphore2.wait()
}
semaphore.signal() //网络请求返回值后,继续等待中的任务
}
semaphore.wait() //执行完异步任务之后,等待
}
print("loop 1 end")
打印结果如下,观察时间,每个请求都是存在间隔,串行执行,效率肯定会低一些,但是胜在条理清晰
🍠模拟第一层请求 回调
☀️模拟一个异步请求下载---2019-07-30 06:29:07 +0000
☀️模拟一个异步请求下载---2019-07-30 06:29:08 +0000
☀️模拟一个异步请求下载---2019-07-30 06:29:09 +0000
🍠模拟第一层请求 回调
☀️模拟一个异步请求下载---2019-07-30 06:29:12 +0000
☀️模拟一个异步请求下载---2019-07-30 06:29:13 +0000
☀️模拟一个异步请求下载---2019-07-30 06:29:14 +0000
🍠模拟第一层请求 回调
☀️模拟一个异步请求下载---2019-07-30 06:29:17 +0000
☀️模拟一个异步请求下载---2019-07-30 06:29:18 +0000
☀️模拟一个异步请求下载---2019-07-30 06:29:19 +0000
loop 1 end
GCD2 (两个DispatchSemaphore)
let group = DispatchGroup.init()
let queue2 = DispatchQueue(label: "default")
let queue = DispatchQueue(label: "concurrent", qos: .userInteractive, attributes: .concurrent)
//并行的queue,用来下载具体数据
let semaphore = DispatchSemaphore(value: 0)
let semaphore2 = DispatchSemaphore(value: 3)
for j in 0...3 {
queue.async(group: group) {
sleep(2)
print("🍠into group - \(j) - \(Thread.current) - \(Date.init(timeIntervalSinceNow: 0))")
for i in 0...2 {
queue.async(group: group) {
sleep(3)
print("🌛into group - \(j) - \(i) - \(Thread.current) - \(Date.init(timeIntervalSinceNow: 0))")
semaphore2.signal()
}
semaphore2.wait()
}
semaphore.signal()
}
semaphore.wait()
}
group.notify(queue: DispatchQueue.main) {
print("通知主界面-组1返回了")
}
打印如下,这种方式,🍠串行, 🌛并行执行
🍠into group - 0 - <NSThread: 0x600000199080>{number = 5, name = (null)} - 2019-07-30 07:22:36 +0000
🍠into group - 1 - <NSThread: 0x6000001a5c40>{number = 6, name = (null)} - 2019-07-30 07:22:38 +0000
🌛into group - 0 - 0 - <NSThread: 0x600000198e00>{number = 4, name = (null)} - 2019-07-30 07:22:39 +0000
🌛into group - 0 - 1 - <NSThread: 0x600000199340>{number = 7, name = (null)} - 2019-07-30 07:22:39 +0000
🌛into group - 0 - 2 - <NSThread: 0x60000019e080>{number = 8, name = (null)} - 2019-07-30 07:22:39 +0000
🌛into group - 1 - 0 - <NSThread: 0x600000199080>{number = 5, name = (null)} - 2019-07-30 07:22:41 +0000
🍠into group - 2 - <NSThread: 0x60000019e080>{number = 8, name = (null)} - 2019-07-30 07:22:41 +0000
🌛into group - 1 - 2 - <NSThread: 0x600000199340>{number = 7, name = (null)} - 2019-07-30 07:22:42 +0000
🌛into group - 1 - 1 - <NSThread: 0x600000198e00>{number = 4, name = (null)} - 2019-07-30 07:22:42 +0000
🌛into group - 2 - 0 - <NSThread: 0x6000001a5c40>{number = 6, name = (null)} - 2019-07-30 07:22:44 +0000
🍠into group - 3 - <NSThread: 0x60000019e080>{number = 8, name = (null)} - 2019-07-30 07:22:44 +0000
🌛into group - 2 - 1 - <NSThread: 0x60000019e380>{number = 9, name = (null)} - 2019-07-30 07:22:44 +0000
🌛into group - 2 - 2 - <NSThread: 0x60000019c4c0>{number = 10, name = (null)} - 2019-07-30 07:22:45 +0000
🌛into group - 3 - 0 - <NSThread: 0x6000001a5c40>{number = 6, name = (null)} - 2019-07-30 07:22:47 +0000
🌛into group - 3 - 1 - <NSThread: 0x600000198e00>{number = 4, name = (null)} - 2019-07-30 07:22:47 +0000
🌛into group - 3 - 2 - <NSThread: 0x600000199340>{number = 7, name = (null)} - 2019-07-30 07:22:47 +0000
通知主界面-组1返回了
OperationQueue
let queue = OperationQueue.init()
queue.maxConcurrentOperationCount = 4
for i in 0...2 {
let sem = DispatchSemaphore(value: 0)
let opration = BlockOperation()
opration.addExecutionBlock { //block 开辟了线程,
let sem1 = DispatchSemaphore(value: 0)
DispatchQueue.global().async { // 使用同步,放弃开辟线程
print("开始模拟一个请求")
sleep(1)
print("🍠返回\(i)- \(Thread.current)- \(Date.init(timeIntervalSinceNow: 0))")
for _ in 0...2 {
let op2 = BlockOperation { //请求2,
// block 中,数据请求也是一个异步,会开辟线程,因此y同样用信号量控制一下执行问题
let sem2 = DispatchSemaphore(value: 0)
DispatchQueue.global().async {
sleep(4)
print("🌞\(i)- \(Thread.current)- \(Date())")
sem2.signal()
}
sem2.wait()
}
queue.addOperation(op2)
}
sem.signal()
}
}
queue.addOperation(opration)
sem.wait()
}
效果如下:保证了对应🍠在🌞之前执行,并且,所有请求放在队列中,并行执行,最大并发数为4,避免大量数据导致峰值。
开始模拟一个请求
🍠返回0- <NSThread: 0x600000478600>{number = 3, name = (null)}- 2019-07-30 07:09:12 +0000
开始模拟一个请求
🍠返回1- <NSThread: 0x600000479480>{number = 6, name = (null)}- 2019-07-30 07:09:13 +0000
🌞0- <NSThread: 0x600000445200>{number = 7, name = (null)}- 2019-07-30 07:09:16 +0000
🌞0- <NSThread: 0x6000004701c0>{number = 8, name = (null)}- 2019-07-30 07:09:16 +0000
🌞0- <NSThread: 0x600000471d00>{number = 9, name = (null)}- 2019-07-30 07:09:16 +0000
开始模拟一个请求
🍠返回2- <NSThread: 0x600000478600>{number = 3, name = (null)}- 2019-07-30 07:09:17 +0000
🌞1- <NSThread: 0x600000471a00>{number = 10, name = (null)}- 2019-07-30 07:09:17 +0000
🌞1- <NSThread: 0x600000445a00>{number = 12, name = (null)}- 2019-07-30 07:09:20 +0000
🌞1- <NSThread: 0x60000047db80>{number = 11, name = (null)}- 2019-07-30 07:09:20 +0000
🌞2- <NSThread: 0x600000470140>{number = 13, name = (null)}- 2019-07-30 07:09:21 +0000
🌞2- <NSThread: 0x600000471a00>{number = 10, name = (null)}- 2019-07-30 07:09:21 +0000
🌞2- <NSThread: 0x600000471d00>{number = 9, name = (null)}- 2019-07-30 07:09:24 +0000