swift GCD 常用 enter - leave - notify

GCD 队列

GCD 队列默认就是串行的(serial)

 let quequ = DispatchQueue()
 let quequ = DispatchQueue(label: "123")

在 GCD 中创建并发队列是如下所示:

let queue = DispatchQueue(label: "current", qos: .default, attributes: .concurrent, autoreleaseFrequency: .never, target: nil)
let queue = DispatchQueue(label: "current", attributes: .concurrent)

label: 队列的标识符,能方便区分队列并调试

qos: 队列的优先级,大多情况下用默认即可

attributes:  队列的属性,默认是串行的,concurrent是并发的,initiallyInactive表示队列不会自动执行,需要开发中调用activate()手动触发,对应的还有suspend() 和 resume()。

  • activate():开始执行队列
  • suspend():挂起队列
  • resume():继续执行队列

autoreleaseFrequency:自动释放频率,有些列队会在执行完任务之后自动释放,有些是不会自动释放的,需要手动释放。

GCD 信号量

DispatchSemaphore 提供了传统计数信号量的高效实现,可用于控制跨多个执行上下文访问资源。

举个例子:线程 A 执行的前提是需要线程 B 执行的结果,但是 A,B 是两个异步线程。简单的来说就是如何串行的执行两个异步线程

let sema = DispatchSemaphore(value: 0)
DispatchQueue.global().async {
    sema.wait()
    print("1")
}
DispatchQueue.global().async {
    sleep(UInt32(2))
    print("2")
    sema.signal()
}
//打印输出为 2,1

上面的代码如果不用信号量处理,输出的结果为 1 2,wait() 就是阻塞当前队列,signal() 发出信号。DispatchSemaphore 的 value 参数表示初始的信号量,不要设置成负数,否则会抛出 EXC_BAD_INSTRUCTION异常。另一个就是要保证 wait() 和 signal() 的平衡,也就是成对的出现。

  • 当一个信号量被通知signal(),计数会加1;
  • 如果一个线程等待一个信号量wait(),线程会被阻塞,直到计数器>0,此时开始运行,并且对信号量减1。

所以先运行到sema.wait()的时候,当前计数器为0,所以阻塞,然后在sema.signal()后,计数器变成1了,此时第一个线程可以执行了。

GCD 线程的同步 enter - leave - notify

当我们想要在并发结束后再同步执行东西。首先我们声明一个线程组  DispatchGroup:

let group = DispatchGroup()

我们需要用到三个方法:enter(),leave(),notify(...)

        let queue = DispatchQueue(label: "concurrent", attributes: .concurrent)
        let group = DispatchGroup()
        group.enter()
        queue.async {
            sleep(UInt32(5))
            print("任务一完成")
            group.leave()
        }
        
        group.enter()
        queue.async {
            sleep(UInt32(8))
            print("任务二完成")
            group.leave()
        }
        
        group.notify(queue: .main) {
            print("最后的任务")
        }
        print("323")
        
        
        //控制台打印如下:
        //323
        //任务一完成
        //任务二完成
        //最后的任务

 直接用队列方法里的group也可以达到上面enter()和leave()的例子,但前提是闭包里执行的得是同步任务才可以,代码如下:

        let group = DispatchGroup.init()
        let queue = DispatchQueue.init(label: "concurrent", attributes: .concurrent)
        queue.async(group: group, qos: DispatchQoS.default) {
            sleep(UInt32(5))
            print("任务一")
        }
        queue.async(group: group, qos: DispatchQoS.default) {
            sleep(UInt32(8))
            print("任务二")
        }
        group.notify(queue: .main) {
            print("最后的任务")
        }
        print("2323")

常用待续。。。

 

OC 线程篇:https://blog.csdn.net/zhangmengleiblog/article/details/103718681

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值