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