美文网首页
多个网络请求做同步异步 解决方案

多个网络请求做同步异步 解决方案

作者: 山已几孑 | 来源:发表于2019-07-30 15:24 被阅读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
    
    

    相关文章

      网友评论

          本文标题:多个网络请求做同步异步 解决方案

          本文链接:https://www.haomeiwen.com/subject/waqnrctx.html