美文网首页
iOS开发 swift -- GCD

iOS开发 swift -- GCD

作者: Hayley__ | 来源:发表于2020-11-10 17:07 被阅读0次

    GCD 简介

    Grand Central Dispatch

    一 任务与队列

    1 任务

    所需要执行的操作

    同步(sync)
    • 不具备开辟新线程的能力
    • 等待队列里的任务完成之后在执行
    异步(async)
    • 不会做任何等待,可以继续执行任务
    • 具备开辟新线程的能力

    2 队列

    这里的队列指执行任务的等待队列,即用来存放任务的队列。队列是一种特殊的线性表,采用 FIFO(先进先出)的原则。

    并发队列(Concurrent Dispatch Queue)
    • 可开辟多条线程,可以同时执行多个任务。
    串行队列 (Serial Dispatch Queue)
    • 只有一条线程,任务一个接着一个地执行,每次只执行一个任务。

    二 创建任务与队列

    1 任务

    • 同步
    queue.sync {
     
    }
    
    • 异步
    queue.async {
     
    }
    

    2 队列

    • 串行队列
    //获取主队列(特殊的串行队列)
    let queue = DispatchQueue.main
    //创建串行队列
    let queue = DispatchQueue(label: "--")
    let queue = DispatchQueue(label: "--", qos: .default, attributes: .init(), autoreleaseFrequency: .inherit, target: nil)
    
    • 并行队列
    //获取全局并发队列
    let queue = DispatchQueue.global()
    let queue = DispatchQueue.global(qos: .default)
    //创建并发队列
    let queue = DispatchQueue(label: "--", qos: .userInteractive, attributes: .concurrent, autoreleaseFrequency: .inherit, target: nil)
    

    三 任务与队列的组合

    1 同步执行 + 并发队列

    • 没有开辟新线程,所有的任务都是在当前线程(主线程)上执行的(同步执行无法开辟新线程)。
    • 任务都是按照顺序执行,执行一个在执行下一个。
        func testGCD() {
            
            let queue = DispatchQueue.global()
    
            print("begin=\(Thread.current)")
            
            queue.sync {
                Thread.sleep(forTimeInterval: 5)
                print("1=====\(Thread.current)")
            }
            
            queue.sync {
                Thread.sleep(forTimeInterval: 7)
                print("2=====\(Thread.current)")
            }
            
            queue.sync {
                Thread.sleep(forTimeInterval: 1)
                print("3=====\(Thread.current)")
            }
            
            queue.sync {
                Thread.sleep(forTimeInterval: 3)
                print("4=====\(Thread.current)")
            }
            
            print("end===\(Thread.current)")
        }
            
    
    //结果
    begin=<NSThread: 0x6000007b01c0>{number = 1, name = main}
    1=====<NSThread: 0x6000007b01c0>{number = 1, name = main}
    2=====<NSThread: 0x6000007b01c0>{number = 1, name = main}
    3=====<NSThread: 0x6000007b01c0>{number = 1, name = main}
    4=====<NSThread: 0x6000007b01c0>{number = 1, name = main}
    end===<NSThread: 0x6000007b01c0>{number = 1, name = main}
    

    2 同步执行 + 串行队列

    • 没有开辟新线程,所有的任务都是在当前线程(主线程)上执行的(同步执行无法开辟新线程)。
    • 任务都是按照顺序执行,执行一个在执行下一个。
        func testGCD() {
            
            let queue = DispatchQueue(label: "Test")
    
            print("begin=\(Thread.current)")
            
            queue.sync {
                Thread.sleep(forTimeInterval: 5)
                print("1=====\(Thread.current)")
            }
            
            queue.sync {
                Thread.sleep(forTimeInterval: 7)
                print("2=====\(Thread.current)")
            }
            
            queue.sync {
                Thread.sleep(forTimeInterval: 1)
                print("3=====\(Thread.current)")
            }
            
            queue.sync {
                Thread.sleep(forTimeInterval: 3)
                print("4=====\(Thread.current)")
            }
            
            print("end===\(Thread.current)")
        }
    
    //结果
    begin=<NSThread: 0x6000012703c0>{number = 1, name = main}
    1=====<NSThread: 0x6000012703c0>{number = 1, name = main}
    2=====<NSThread: 0x6000012703c0>{number = 1, name = main}
    3=====<NSThread: 0x6000012703c0>{number = 1, name = main}
    4=====<NSThread: 0x6000012703c0>{number = 1, name = main}
    end===<NSThread: 0x6000012703c0>{number = 1, name = main}
    

    3 同步执行 + 主队列

    • 相互阻塞卡死
    • testGCD在主线程上执行,任务1-4也在主线程上执行,testGCD等待任务执行,任务等待testGCD执行,相互等待卡死线程。
        func testGCD() {
            
            let queue = DispatchQueue.main
    
            print("begin=\(Thread.current)")
            
            queue.sync {
                Thread.sleep(forTimeInterval: 5)
                print("1=====\(Thread.current)")
            }
            
            queue.sync {
                Thread.sleep(forTimeInterval: 7)
                print("2=====\(Thread.current)")
            }
            
            queue.sync {
                Thread.sleep(forTimeInterval: 1)
                print("3=====\(Thread.current)")
            }
            
            queue.sync {
                Thread.sleep(forTimeInterval: 3)
                print("4=====\(Thread.current)")
            }
            
            print("end===\(Thread.current)")
        }
    
    //结果
    begin=<NSThread: 0x600002920900>{number = 1, name = main}
    (lldb) 
    

    4 同步执行 + 主队列(其他线程)

    • 所有任务在主线程中执行,非当前线程,任务按照顺序执行。
    • testGCD不在主线程上执行,与任务不在同一线程,不会卡住。
            Thread.detachNewThread {
                self.testGCD()
            }
    
    //结果
    begin=<NSThread: 0x600003b1e480>{number = 6, name = (null)}
    1=====<NSThread: 0x600003b741c0>{number = 1, name = main}
    2=====<NSThread: 0x600003b741c0>{number = 1, name = main}
    3=====<NSThread: 0x600003b741c0>{number = 1, name = main}
    4=====<NSThread: 0x600003b741c0>{number = 1, name = main}
    end===<NSThread: 0x600003b1e480>{number = 6, name = (null)}
    

    5 异步执行 + 串行队列

    • 创建一个新线程
    • 异步执行不做任何等待。
    • 串行队列任务按照顺序执行。
        func testGCD() {
            
            let queue = DispatchQueue(label: "Test")
    
            print("begin=\(Thread.current)")
            
            queue.async {
                Thread.sleep(forTimeInterval: 5)
                print("1=====\(Thread.current)")
            }
            
            queue.async {
                Thread.sleep(forTimeInterval: 7)
                print("2=====\(Thread.current)")
            }
            
            queue.async {
                Thread.sleep(forTimeInterval: 1)
                print("3=====\(Thread.current)")
            }
            
            queue.async {
                Thread.sleep(forTimeInterval: 3)
                print("4=====\(Thread.current)")
            }
            
            print("end===\(Thread.current)")
        }
    
    //结果
    begin=<NSThread: 0x6000008b01c0>{number = 1, name = main}
    end===<NSThread: 0x6000008b01c0>{number = 1, name = main}
    1=====<NSThread: 0x6000008a27c0>{number = 4, name = (null)}
    2=====<NSThread: 0x6000008a27c0>{number = 4, name = (null)}
    3=====<NSThread: 0x6000008a27c0>{number = 4, name = (null)}
    4=====<NSThread: 0x6000008a27c0>{number = 4, name = (null)}
    

    6 异步执行 + 并发队列

    • 会开辟多条新线程。
    • 任务交替执行不做任何等待。
        func testGCD() {
            
            let queue = DispatchQueue.global()
    
            print("begin=\(Thread.current)")
            
            queue.async {
                Thread.sleep(forTimeInterval: 5)
                print("1=====\(Thread.current)")
            }
            
            queue.async {
                Thread.sleep(forTimeInterval: 7)
                print("2=====\(Thread.current)")
            }
            
            queue.async {
                Thread.sleep(forTimeInterval: 1)
                print("3=====\(Thread.current)")
            }
            
            queue.async {
                Thread.sleep(forTimeInterval: 3)
                print("4=====\(Thread.current)")
            }
            
            print("end===\(Thread.current)")
        }
    
    //结果
    begin=<NSThread: 0x600001f84280>{number = 1, name = main}
    end===<NSThread: 0x600001f84280>{number = 1, name = main}
    3=====<NSThread: 0x600001fdde80>{number = 3, name = (null)}
    4=====<NSThread: 0x600001fe0940>{number = 7, name = (null)}
    1=====<NSThread: 0x600001f887c0>{number = 4, name = (null)}
    2=====<NSThread: 0x600001f88d80>{number = 5, name = (null)}
    

    7 异步执行 + 主队列

    • 在主线程中执行,没有开辟新线程,在主队列中放入主线程中执行。
    • 异步执行不做任何等待。
    • 任务按顺序执行,因为主线程是串行队列。
        func testGCD() {
            
            let queue = DispatchQueue.main
    
            print("begin=\(Thread.current)")
            
            queue.async {
                Thread.sleep(forTimeInterval: 5)
                print("1=====\(Thread.current)")
            }
            
            queue.async {
                Thread.sleep(forTimeInterval: 7)
                print("2=====\(Thread.current)")
            }
            
            queue.async {
                Thread.sleep(forTimeInterval: 1)
                print("3=====\(Thread.current)")
            }
            
            queue.async {
                Thread.sleep(forTimeInterval: 3)
                print("4=====\(Thread.current)")
            }
            
            print("end===\(Thread.current)")
        }
    
    //结果
    begin=<NSThread: 0x6000013b83c0>{number = 1, name = main}
    end===<NSThread: 0x6000013b83c0>{number = 1, name = main}
    1=====<NSThread: 0x6000013b83c0>{number = 1, name = main}
    2=====<NSThread: 0x6000013b83c0>{number = 1, name = main}
    3=====<NSThread: 0x6000013b83c0>{number = 1, name = main}
    4=====<NSThread: 0x6000013b83c0>{number = 1, name = main}
    

    四 线程间的通讯

    • 主线程刷新应用
        func testGCD() {
            
            let queue = DispatchQueue.global()
    
            print("begin=\(Thread.current)")
            
            queue.async {
                Thread.sleep(forTimeInterval: 5)
                print("1=====\(Thread.current)")
                
                DispatchQueue.main.async {
                    print("2=====\(Thread.current)")
                }
            }
    
            print("end===\(Thread.current)")
        }
    
    //结果
    begin=<NSThread: 0x600000a081c0>{number = 1, name = main}
    end===<NSThread: 0x600000a081c0>{number = 1, name = main}
    1=====<NSThread: 0x600000a55000>{number = 6, name = (null)}
    2=====<NSThread: 0x600000a081c0>{number = 1, name = main}
    

    五 其他应用方式

    1 队列组:dispatch_group

    • group.notify 同时执行多个异步耗时请求,最终回到主线程。
        func testGCD() {
            
            let queue = DispatchQueue(label: "test", qos: .default, attributes: .concurrent, autoreleaseFrequency: .inherit, target: nil)
            
            let group = DispatchGroup()
            
            print("begin=\(Thread.current)")
            
            queue.async(group: group, qos: .default, flags: .inheritQoS) {
                Thread.sleep(forTimeInterval: 5)
                print("1=====\(Thread.current)")
            }
            
            queue.async(group: group, qos: .default, flags: .inheritQoS) {
                Thread.sleep(forTimeInterval: 7)
                print("2=====\(Thread.current)")
            }
    
            queue.async(group: group, qos: .default, flags: .inheritQoS) {
                Thread.sleep(forTimeInterval: 5)
                print("3=====\(Thread.current)")
            }
            
            queue.async(group: group, qos: .default, flags: .inheritQoS) {
                Thread.sleep(forTimeInterval: 7)
                print("4=====\(Thread.current)")
            }
    
            group.notify(queue: DispatchQueue.main) {
                print("notify\(Thread.current)")
            }
            
            print("end===\(Thread.current)")
            
            queue.async(group: group, qos: .default, flags: .inheritQoS) {
                Thread.sleep(forTimeInterval: 7)
                print("5=====\(Thread.current)")
            }
    
        }
    
    //结果
    begin=<NSThread: 0x60000033c1c0>{number = 1, name = main}
    end===<NSThread: 0x60000033c1c0>{number = 1, name = main}
    3=====<NSThread: 0x60000037c280>{number = 5, name = (null)}
    1=====<NSThread: 0x600000366840>{number = 7, name = (null)}
    5=====<NSThread: 0x60000037c140>{number = 3, name = (null)}
    2=====<NSThread: 0x600000366a80>{number = 6, name = (null)}
    4=====<NSThread: 0x60000032a3c0>{number = 9, name = (null)}
    notify<NSThread: 0x60000033c1c0>{number = 1, name = main}
    
    • group.enter() 未执行任务+1, group.leave() 未执行任务-1, 未执行任务=0,才会解除阻塞,继续执行后续代码。
        func testGCD() {
            
            let queue = DispatchQueue(label: "test", qos: .default, attributes: .concurrent, autoreleaseFrequency: .inherit, target: nil)
            
            let group = DispatchGroup()
            
            print("begin=\(Thread.current)")
            
            group.enter()
            queue.async {
                Thread.sleep(forTimeInterval: 5)
                print("1=====\(Thread.current)")
                group.leave()
            }
    
            
            group.enter()
            queue.async {
                Thread.sleep(forTimeInterval: 7)
                print("2=====\(Thread.current)")
                group.leave()
            }
    
            group.enter()
            queue.async {
                Thread.sleep(forTimeInterval: 5)
                print("3=====\(Thread.current)")
                group.leave()
            }
            
            group.notify(queue: DispatchQueue.main) {
                print("notify\(Thread.current)")
            }
            
            print("end===\(Thread.current)")
        }
    
    //结果
    begin=<NSThread: 0x6000036e0a40>{number = 1, name = main}
    end===<NSThread: 0x6000036e0a40>{number = 1, name = main}
    3=====<NSThread: 0x6000036a1bc0>{number = 5, name = (null)}
    1=====<NSThread: 0x600003688040>{number = 3, name = (null)}
    2=====<NSThread: 0x6000036be100>{number = 4, name = (null)}
    notify<NSThread: 0x6000036e0a40>{number = 1, name = main}
    
    • group.wait() 阻塞当前线程,暂停当前线程。wait后面所有代码都不执行。
        func testGCD() {
            
            let queue = DispatchQueue(label: "test", qos: .default, attributes: .concurrent, autoreleaseFrequency: .inherit, target: nil)
            
            let group = DispatchGroup()
            
            print("begin=\(Thread.current)")
            
            queue.async(group: group, qos: .default, flags: .inheritQoS) {
                Thread.sleep(forTimeInterval: 5)
                print("1=====\(Thread.current)")
            }
            
            queue.async(group: group, qos: .default, flags: .inheritQoS) {
                Thread.sleep(forTimeInterval: 7)
                print("2=====\(Thread.current)")
            }
    
            queue.async(group: group, qos: .default, flags: .inheritQoS) {
                Thread.sleep(forTimeInterval: 5)
                print("3=====\(Thread.current)")
            }
            
            queue.async(group: group, qos: .default, flags: .inheritQoS) {
                Thread.sleep(forTimeInterval: 7)
                print("4=====\(Thread.current)")
            }
            
            group.wait()
            
            queue.async(group: group, qos: .default, flags: .inheritQoS) {
                Thread.sleep(forTimeInterval: 7)
                print("5=====\(Thread.current)")
            }
    
            group.notify(queue: DispatchQueue.main) {
                print("notify\(Thread.current)")
            }
            
            print("end===\(Thread.current)")
        }
    
    //结果
    begin=<NSThread: 0x600000484900>{number = 1, name = main}
    3=====<NSThread: 0x6000004ddec0>{number = 7, name = (null)}
    1=====<NSThread: 0x6000004e4040>{number = 6, name = (null)}
    4=====<NSThread: 0x6000004d4700>{number = 8, name = (null)}
    2=====<NSThread: 0x6000004cb500>{number = 5, name = (null)}
    end===<NSThread: 0x600000484900>{number = 1, name = main}
    5=====<NSThread: 0x6000004cb500>{number = 5, name = (null)}
    notify<NSThread: 0x600000484900>{number = 1, name = main}
    
    • group.barrier 不会阻塞线程,group中barrier后的代码后执行。
        func testGCD() {
    
            let queue = DispatchQueue(label: "test", qos: .default, attributes: .concurrent, autoreleaseFrequency: .inherit, target: nil)
    
            let group = DispatchGroup()
    
            print("begin=\(Thread.current)")
    
            queue.async(group: group, qos: .default, flags: .inheritQoS) {
                Thread.sleep(forTimeInterval: 5)
                print("1=====\(Thread.current)")
            }
    
            queue.async(group: group, qos: .default, flags: .inheritQoS) {
                Thread.sleep(forTimeInterval: 7)
                print("2=====\(Thread.current)")
            }
    
            queue.async(group: group, qos: .default, flags: .inheritQoS) {
                Thread.sleep(forTimeInterval: 5)
                print("3=====\(Thread.current)")
            }
    
            queue.async(group: group, qos: .default, flags: .barrier) {
                print("barrier==\(Thread.current)")
            }
    
            queue.async(group: group, qos: .default, flags: .inheritQoS) {
                Thread.sleep(forTimeInterval: 7)
                print("4=====\(Thread.current)")
            }
    
            group.notify(queue: DispatchQueue.main) {
                print("notify\(Thread.current)")
            }
    
            print("end===\(Thread.current)")
        }
    
    //结果
    begin=<NSThread: 0x6000038c83c0>{number = 1, name = main}
    end===<NSThread: 0x6000038c83c0>{number = 1, name = main}
    3=====<NSThread: 0x6000038c00c0>{number = 8, name = (null)}
    1=====<NSThread: 0x600003880ec0>{number = 6, name = (null)}
    2=====<NSThread: 0x600003894400>{number = 5, name = (null)}
    barrier==<NSThread: 0x600003894400>{number = 5, name = (null)}
    4=====<NSThread: 0x600003894400>{number = 5, name = (null)}
    notify<NSThread: 0x6000038c83c0>{number = 1, name = main}
    

    2 延时执行

    • 延迟执行任务
            queue.asyncAfter(deadline: .now() + 3) {
                print("after=\(Thread.current)")
            }
    

    3 信号量

    • 保持线程同步
    • 保证线程安全
        func testGCD() {
            
            let queue = DispatchQueue.global()
            
            //创建一个 Semaphore 并初始化信号的总量
            let semaphore = DispatchSemaphore(value: 0)
            
            print("begin====\(Thread.current)")
    
            queue.async {
                Thread.sleep(forTimeInterval: 5)
                print("signal===\(Thread.current)")
    
                //发送一个信号,让信号总量加 1
                semaphore.signal()
            }
            
            //可以使总信号量减 1,信号总量小于 0 时就会一直等待(阻塞所在线程),否则就可以正常执行。
            semaphore.wait()
            
            print("end======\(Thread.current)")
        }
    
    //结果
    begin====<NSThread: 0x600001970a40>{number = 1, name = main}
    signal===<NSThread: 0x6000019342c0>{number = 7, name = (null)}
    end======<NSThread: 0x600001970a40>{number = 1, name = main}
    
    • 线程加锁
        func initMoney() {
            semaphore = DispatchSemaphore(value: 1)
            money = 10
            let queueOne = DispatchQueue(label: "queueOne")
            let queueTwo = DispatchQueue(label: "queueTwo")
            let queueThree = DispatchQueue(label: "queueThree")
            queueOne.async {
                self.takeMoney()
            }
            
            queueTwo.async {
                self.takeMoney()
            }
            
            queueThree.async {
                self.takeMoney()
            }
            
        }
        
        func takeMoney() {
            while (1 != 0) {
                semaphore.wait()
                if money > 0 {
                    money = money - 1
                    print("money==\(String(describing: money))==\(Thread.current)")
                } else {
                    print("no money====\(Thread.current)")
                    semaphore.signal()
                    break
                }
                semaphore.signal()
            }
        }
    
    //结果
    money==Optional(9)==<NSThread: 0x6000023a4fc0>{number = 7, name = (null)}
    money==Optional(8)==<NSThread: 0x6000023f5d80>{number = 6, name = (null)}
    money==Optional(7)==<NSThread: 0x600002390900>{number = 5, name = (null)}
    money==Optional(6)==<NSThread: 0x6000023a4fc0>{number = 7, name = (null)}
    money==Optional(5)==<NSThread: 0x6000023f5d80>{number = 6, name = (null)}
    money==Optional(4)==<NSThread: 0x600002390900>{number = 5, name = (null)}
    money==Optional(3)==<NSThread: 0x6000023a4fc0>{number = 7, name = (null)}
    money==Optional(2)==<NSThread: 0x6000023f5d80>{number = 6, name = (null)}
    money==Optional(1)==<NSThread: 0x600002390900>{number = 5, name = (null)}
    money==Optional(0)==<NSThread: 0x6000023a4fc0>{number = 7, name = (null)}
    no money====<NSThread: 0x6000023f5d80>{number = 6, name = (null)}
    no money====<NSThread: 0x600002390900>{number = 5, name = (null)}
    no money====<NSThread: 0x6000023a4fc0>{number = 7, name = (null)}
    

    相关文章

      网友评论

          本文标题:iOS开发 swift -- GCD

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