iOS多线程 - Queue



  • Swift版本: 4.0

    通过 Queue 可以进行多线程编程。

    • 获取队列
    // 串行队列
    let serialQueue = DispatchQueue(label: "com.zzb.serial")
    // 并行队列
    let consurrentQueue = DispatchQueue(label: "com.zzb.concurrent", attributes: .concurrent)
    
    // 主队列
    let mainQueue = DispatchQueue.main
    // 全局队列
    let globalQueue = DispatchQueue.global()
    
    // 队列优先级从高到低(QoSClass)
    // userInteractive
    // userInitiated
    // default
    // utility
    // background
    // unspecified
    let backgroundQueue = DispatchQueue.global(qos: .background)
    
    // 自定义队列 - 高优先级
    let serialQueueHighPriority = DispatchQueue(label: "com.zzb.highSerial", qos: .userInteractive)
    
    • 异步执行
    globalQueue.async {
        print("globalQueue async execute")
    }
    
    • 同步执行
    globalQueue.sync {
        print("globalQueue sync execute")
    }
    
    • 后台执行任务,然后主线程更新UI
    DispatchQueue.global(qos: .background).async {
        // TODO: 后台运行的代码
    
        DispatchQueue.main.async {
            print("UI thread execute")
        }
    }
    
    • 延时执行
    globalQueue.asyncAfter(deadline: .now() + .seconds(2)) {
        print("Execute after 2s")
    }
    
    • 同时执行一个相同的闭包
    globalQueue.sync {
        DispatchQueue.concurrentPerform(iterations: 5) {
            print("\($0) times")
        }
    }
    
    • 手动激活队列任务
    // 手动激活队列任务
    let inactiveQueue = DispatchQueue(label: "com.zzb.inactiveQueue", attributes: [.concurrent, .initiallyInactive])
    inactiveQueue.async {
        print("inactiveQueue execute")
    }
    print("inactiveQueue not start")
    inactiveQueue.activate()
    
    // 挂起
    inactiveQueue.suspend()
    // 恢复
    inactiveQueue.resume()
    
    • 屏障(barrier)
    // 通过 屏障(barrier) 实现所有异步任务完成后再执行一个任务
    // 屏障不能作用于串行队列或者任何一种类型的全局并行队列,如果你想使用它,就必须自定义一个全新的并行队列。
    let concurrentQueue2 = DispatchQueue(label: "com.zzb.concurrent", attributes: .concurrent)
    concurrentQueue2.async {
        DispatchQueue.concurrentPerform(iterations: 5) { (id: Int) in
            sleep(1)
            print("concurrentQueue2 execute 5 times, current id = \(id)")
        }
    }
    
    concurrentQueue2.async(flags: .barrier) {
        print("All 5 concurrent tasks completed")
    }
    

    将输出如下类似日志

    concurrentQueue2 execute 5 times, current id = 2
    concurrentQueue2 execute 5 times, current id = 4
    concurrentQueue2 execute 5 times, current id = 0
    concurrentQueue2 execute 5 times, current id = 3
    concurrentQueue2 execute 5 times, current id = 1
    All 5 concurrent tasks completed
    
    • DispatchGroup,一旦所有任务完成以后,将会在队列中执行一个闭包,wait()方法用于执行阻塞等待
    let dispatchGroup = DispatchGroup()
    
    for i in 0..<5 {
        globalQueue.async(group: dispatchGroup) {
            sleep(UInt32(i))
            print("Group async on globalQueue: \(i)")
        }
    }
    
    print("Waiting for completion")
    dispatchGroup.notify(queue: globalQueue) {
        print("dispatchGroup notify")
    }
    
    print("dispatchGroup begin wait")
    dispatchGroup.wait()
    print("dispatchGroup wait done")
    

    将输出如下日志

    Waiting for completion
    dispatchGroup begin wait
    Group async on globalQueue: 0
    Group async on globalQueue: 1
    Group async on globalQueue: 2
    Group async on globalQueue: 3
    Group async on globalQueue: 4
    dispatchGroup wait done
    dispatchGroup notify
    
    • 手动在运行队列代码调用中进入和离开一个组
    let dispatchGroup = DispatchGroup()
    
    for i in 0..<5 {
        dispatchGroup.enter()
    
        sleep(UInt32(i))
        print("Group sync i = \(i)")
    
        dispatchGroup.leave()
    }
    

    将输出如下日志

    Group sync i = 0
    Group sync i = 1
    Group sync i = 2
    Group sync i = 3
    Group sync i = 4
    
    • DispatchWorkItem
    let workItem = DispatchWorkItem {
        print("workItem done")
    }
    
    workItem.notify(queue: DispatchQueue.main) {
        print("workItem notify")
    }
    
    DispatchQueue.main.async(execute: workItem)
    

    将输出如下日志

    workItem done
    workItem notify
    
    • DispatchSemaphore
    let dispatchSemaphore = DispatchSemaphore(value: 2)
    
    let globalQueue = DispatchQueue.global()
    
    globalQueue.sync {
        DispatchQueue.concurrentPerform(iterations: 10) { (id: Int) in
            _ = dispatchSemaphore.wait(timeout: DispatchTime.distantFuture)
            sleep(3)
            print("\(id) acquired semaphore")
            dispatchSemaphore.signal()
        }
    }
    

    设置的信号量限值为2,当2个都被占有的时候,其它线程将进入wait状态,直到原先占有信号量的线程发出signal()来释放信号。

    将输出如下日志

    0 acquired semaphore
    1 acquired semaphore
    3 acquired semaphore
    4 acquired semaphore
    2 acquired semaphore
    5 acquired semaphore
    6 acquired semaphore
    7 acquired semaphore
    8 acquired semaphore
    9 acquired semaphore
    
    • dispatchPrecondition
    dispatchPrecondition(condition: .notOnQueue(DispatchQueue.main))
    

    该段代码表示的是如果当前执行的线程非主线程的话,程序将中断。

    • DispatchSource
    let dispatchSourceTimer = DispatchSource.makeTimerSource()
    
    private func testDispatchSource() {
        dispatchSourceTimer.setEventHandler {
            print("dispatchSourceTimer event handle")
        }
        dispatchSourceTimer.schedule(deadline: .now() + .seconds(2))
        
        dispatchSourceTimer.activate()
    }
    

    执行testDispatchSource(),2秒后将输出如下日志

    dispatchSourceTimer event handle
    
    • OperationQueue
    let queue = OperationQueue()
    queue.name = "zzb"
    queue.maxConcurrentOperationCount = 2
    
    queue.addOperation {
        print("op1")
    }
    
    queue.addOperation {
        print("op2")
    }
    
    // BlockOperation
    let op3 = BlockOperation {
        print("op3")
    }
    op3.queuePriority = .veryHigh
    op3.completionBlock = {
        print("op3 completionBlock")
    }
    
    let op4 = BlockOperation {
        print("op4")
        OperationQueue.main.addOperation {
            print("op4 main queue")
        }
    }
    
    op4.addDependency(op3)  // op4依赖于op3,意味着op3将会先于op4执行
    queue.addOperation(op4)
    queue.addOperation(op3)
    

    将输出如下日志

    op1
    op2
    op3
    op3 completionBlock
    op4
    op4 main queue
    

    Demo源码

    https://github.com/CaryZheng/iOSTutorials

    参考资料

    http://swift.gg/2017/09/04/all-about-concurrency-in-swift-1-the-present


Log in to reply