之前博客有说过iOS中的多线程这边就不详细介绍了,这边就来说说iOS中的GCD
多线程离不开同步异步,GCD也是一样的同步(sync)和异步(async)
CGD基本使用:
//qos:background服务质量 后台执行
//qos:default 正常服务质量
//attributes:concurrent可以指定是串行队列还是并行队列
//如果没有指定concurrent则是串行,否则并行
//autoreleaseFrequency:inherit 继承方式
let queue = DispatchQueue.init(label: "myQueue", qos: .default, attributes: .concurrent, autoreleaseFrequency: .inherit, target: nil)
queue.sync {
sleep(1)
print("in queue sync")
}
print("after invoke queue method")
sync输出结果
in queue sync
after inboke queue method
queue.async {
sleep(1)
print("in queue sync")
}
print("after invoke queue method")
async输出结果
after inboke queue method
in queue sync
asyncAfter输出结果
queue.asyncAfter(deadline: .now() + 1) {
print("in asyncAfter")
}
print("after invoke queue method")
asyncAfter输出结果
after inboke queue method
in queue sync
GCD的高级特性
DispatchGroup
顾名思义将多个任务进行分组
如图所示Group有两个方法分别是enter和leave,这边必须注意enter和leave必须成对出现才能得到DispatchGroup的效果。
应用场景,比如多个网络请求的时候我们要用到其中的数据作为输入,这时候就可以根据多个网络请求的组成的结果作为wait的输入。这是就可以把网络请求发出的时候作为enter,返回的时候作为leave。当多个请求都执行到了leave这时候就可以去做wait之后的数据了。
使用DispatchGroup-wait使用代码如下:
let workingGroup = DispatchGroup()
let workingQueue = DispatchQueue(label: "request_queue")
workingGroup.enter()
workingQueue.async {
Thread.sleep(forTimeInterval: 1)
print("接口一请求完成")
workingGroup.leave()
}
workingGroup.enter()
workingQueue.async {
Thread.sleep(forTimeInterval: 1)
print("接口二请求完成")
workingGroup.leave()
}
print("我是最开始执行的,在异步打印后执行")
workingGroup.wait()
print("接口一和接口二请求已经完毕,开始处理这俩的数据")
输出结果如下:
我是最开始执行的,在异步打印后执行
接口一请求完成
接口二请求完成
接口一和接口二请求已经完毕,开始处理这俩的数据
注意⚠️接口一和接口二的请求顺序一定,因为Queue是串行队列。
为什么是串行队列,👆有介绍哦!
如果把它变成并行队列呢?
let workingGroup = DispatchGroup()
let queue = DispatchQueue.init(label: "myQueue", qos: .default, attributes: .concurrent, autoreleaseFrequency: .inherit, target: nil)
workingGroup.enter()
queue.async {
sleep(2)
print("接口一请求完成")
workingGroup.leave()
}
workingGroup.enter()
queue.async {
sleep(1)
print("接口二请求完成")
workingGroup.leave()
}
print("group enter 调用完成")
workingGroup.wait()
print("接口一和接口二请求已经完毕,开始处理这俩的数据")
输出结果如下:
group enter 调用完成
接口二请求完成
接口一请求完成
接口一和接口二请求已经完毕,开始处理这俩的数据
注意 这时候就要看两个queue的执行顺序了,接口一和二的执行顺序不一定了。
workingGroup-notify使用代码如下:
let workingGroup = DispatchGroup()
let workingQueue = DispatchQueue(label: "request_queue")
workingGroup.enter()
workingQueue.async {
Thread.sleep(forTimeInterval: 1)
print("接口一请求完成")
workingGroup.leave()
}
workingGroup.enter()
workingQueue.async {
Thread.sleep(forTimeInterval: 1)
print("接口二请求完成")
workingGroup.leave()
}
print("我是最开始执行的,在异步打印后执行")
workingGroup.notify(queue: workingQueue) {
print("接口一和接口二请求已经完毕,开始处理这俩的数据")
}
print("验证不堵塞")
输出结果如下:
我是最开始执行的,在异步打印后执行
验证不堵塞
接口一请求完成
接口二请求完成
接口一和接口二请求已经完毕,开始处理这俩的数据
DispatchSource
简单来说,dispatchSource是一个监视某些事件的对象。当这些事件发生时,它自动将一个task放入dispatchQueue的执行历程中。
var second = 10
let queue = DispatchQueue.init(label: "myQueue", qos: .default, attributes: .concurrent, autoreleaseFrequency: .inherit, target: nil)
let timer = DispatchSource.makeTimerSource(flags: [], queue: queue)
timer.schedule(deadline: .now(), repeating: 1.0)
timer.setEventHandler {
second -= 1
if second < 0{
timer.cancel()
}else{
print(second)
}
}
timer.resume()
输出如下
9
8
7
6
5
4
3
2
1
0