GCD进阶之DispatchWorkItem和DispatchG
2017-10-20 本文已影响1909人
flionel
playground-line.jpg
1.2 执行结束通过
2.2 所有任务执行结束,通过
1. DispatchWorkItem简介
DispatchWorkItem是帮助DispatchQueue来执行队列中的任务的,它的初始化方法定义如下代码,
public init(qos: DispatchQoS = default, flags: DispatchWorkItemFlags = default, block: @escaping @convention(block) () -> Swift.Void)
初始化方法可以传入一个闭包
,闭包中就是需要执行的任务,通过perform()
方法来唤起该DispatchWorkItem来执行任务,
var value = 10
let workItem = DispatchWorkItem {
value += 5
}
workItem.perform()
1.1 队列中执行DispatchWorkItem的任务
也可以通过队列来同步或异步地执行DispatchWorkItem中的任务,如下代码所示,
let queue = DispatchQueue.global(qos: .utility)
queue.async {
workItem.perform()
}
当然还可以通过下面的方法来执行,这样代码无疑简洁了很多,
queue.async(execute: workItem)
print("value is \(value)")
1.2 执行结束通过notify
提示主队列
workItem.notify(queue: DispatchQueue.main) {
print("value = ", value)
}
print("value is \(value)")
2 DispatchGroup简介
一个队列执行多个任务或多个队列执行不同任务,怎样知道所有的任务都执行完毕呢,这时可以使用DispatchGroup来解决这个需求。
2.1 创建DispatchGroup,将队列加入Group
let queue = DispatchQueue(label: "com.flion.dispatchgroup", attributes: .concurrent)
let group = DispatchGroup()
// group.enter()
queue.async(group: group) {
print("doing stuff")
// group.leave()
}
//group.enter()
queue.async(group: group) {
print("doing more stuff again")
// group.leave()
}
2.2 所有任务执行结束,通过notify
提示主线程
group.notify(queue: Dispatch.main) {
print("done doing all stuff")
}
3 GCD的应用场景以及思考
GCD的概念相对较多,使用也很灵活,在使用过程中应该避免线程死锁,以下笔者根据自己的业务场景总结的一些使用经验,如有错误,还请指正,
3.1 多个任务需要需要依次执行
例如先打开冰箱
,塞入食品
,关上冰箱
,此时可以将这些任务放入串行队列中执行,如下代码所示,
let serialQueue = DispatchQueue(label: "com.flion.serialQueue", qos: .default)
serialQueue.async {
print("打开冰箱")
}
serialQueue.async {
print("塞入食品")
}
serialQueue.async {
print("关上冰箱")
}
3.2 多个任务执行完成之后再执行后续代码
例如,煮饭、烧开水、做4道小菜,吃饭,煮饭和烧开水可以靠电器来执行,做菜需要靠我自己来做,那么这3件事情是可以同时进行的,只有这3件事情做完才可以开始吃饭,可以将这3件事情放入并行队列,并通过DispatchGroup来执行,如下代码所示,
let group = DispatchGroup()
let queue1 = DispatchQueue(label: "com.flion.queue1", qos: .default, attributes: .concurrent)
queue1.async(group: group) {
print("烧开水")
Thread.sleep(forTimeInterval: 2)
}
queue1.async(group: group) {
print("煮米饭")
Thread.sleep(forTimeInterval: 2)
}
queue1.async(group: group) {
print("做4道小菜")
Thread.sleep(forTimeInterval: 2)
}
group.notify(queue: DispatchQueue.main) {
print("开始吃饭喽")
}
当然也可以创建3个队列,并通过DispatchGroup来执行,执行结束之后notify
提示主线程,
let group = DispatchGroup()
let queue1 = DispatchQueue(label: "com.flion.queue1", qos: .default, attributes: .concurrent)
queue1.async(group: group) {
print("烧开水")
Thread.sleep(forTimeInterval: 2)
}
let queue2 = DispatchQueue(label: "com.flion.queue1", qos: .default, attributes: .concurrent)
queue2.async(group: group) {
print("煮米饭")
Thread.sleep(forTimeInterval: 2)
}
let queue3 = DispatchQueue(label: "com.flion.queue1", qos: .default, attributes: .concurrent)
queue3.async(group: group) {
print("做4道小菜")
Thread.sleep(forTimeInterval: 2)
}
group.notify(queue: DispatchQueue.main) {
print("开始吃饭喽")
}
3.3 再说一说DispatchWorkItem
读者可以看到,在上面的开冰箱
和吃饭
的代码中并没有使用DispatchWorkItem,在我看来使用WorkItem可以使代码更加简洁,它将业务内聚,将模块分离。当然也可以完全不适用WorkItem,这看开发者的喜好了。
GCD的使用非常灵活,读者朋友应该多多尝试,深入理解GCD中的同步、异步,串行、并行的概念,这样才能记忆深刻。