【Swift开发】DispatchGroup和信号量

前段时间,再次使用Swift的DispatchGroup。感觉非常好用,就分享出来。

概念
DispatchGroup是Swift中的一个类,主要作用是管理多个异步任务的执行,具体来说,等待一组任务全部完成后再执行后续操作。这种方式在开发的某些场景非常有用。

使用方法
1.创建DispatchGroup对象,例如 let group = DispatchGroup()
2.使用group.enter()方法进入组,表示有一个任务要执行。
3.在异步任务中,使用group.leave()方法离开组,表示任务执行完毕。
4.最后,当所有任务都执行完毕时,会调用group.notify(),结束当前一组任务,执行后续操作。

四个方法
enter: 进入一个任务组
leave: 离开一个任务组
wait: 等待组内任务完成
notify:组内所有任务完成,通知执行后续操作。

使用场景
1.并行执行多个网络请求。当需要一次性发起多个网络请求,并等每个请求完成之后,再一起处理,就可以使用DispatchGroup来实现。
2.异步任务依赖关系:当有多个异步任务有先后次序依赖关系,需要按次序一个一个地执行,前一个任务没有执行完,不执行下一个任务的,可以使用DispatchGroup来实现。
3.批量处理数据:当需要对一批数据进行批量处理,在所有处理完成后,才能进行下一步操作时,可以使用DispatchGroup来实现。

具体实践
直接上代码.
func dealWithTasks() {

let group = DispatchGroup()
let queue = DispatchQueue(label: "my.queue.request")

group.enter()
queue.async {
    Thread.sleep(forTimeInterval: 1.0)
    print("Task 1 Finished")
    group.leave()
}

group.enter()
queue.async {
    Thread.sleep(forTimeInterval: 1.0)
    print("Task 2 Finished")
    group.leave()
}

group.enter()
queue.async {
    Thread.sleep(forTimeInterval: 1.0)
    print("Task 3 Finished")
    group.leave()
}

print("First exe, and then three's async")

group.notify(queue: queue) {

    print("All Task have been finished")
    //todo next
}
print("the end")

}
上述代码创建了三个任务,并且三个任务都执行完以后,在一次通知执行后续的操作。
这里要注意:因是异步执行,所有首先执行的是第27行代码,然后是34行,最后才是async里面的代码。

执行结果如下:
First exe, and then three’s async
the end
Task 1 Finished
Task 2 Finished
Task 3 Finished
All Task have been finished

加上 wait方法
上述代码保证了三个任务执行完后,再执行notify。但是不能保证三个任务是依次先后执行的,即先执行任务1,再任务2,再任务3。那又如何来实现任务1,2,3按次序执行呢?那就要用到wait方法了。
func dealWithTasksOneByOne() {

let group = DispatchGroup()
let queue = DispatchQueue(label: "my.queue.request")

group.enter()
queue.async {
    Thread.sleep(forTimeInterval: 1.0)
    print("Task 1 Finished")
    group.leave()
}

group.wait()

group.enter()
queue.async {
    Thread.sleep(forTimeInterval: 1.0)
    print("Task 2 Finished")
    group.leave()
}

group.wait()

group.enter()
queue.async {
    Thread.sleep(forTimeInterval: 1.0)
    print("Task 3 Finished")
    group.leave()
}

group.wait()

print("First exe, and then three's async")

group.notify(queue: queue) {

    print("All Task have been finished")
    //todo next
}

print("the end")

}
上述代码保证了任务1,2,3依次执行,并且block外的代码也是依次执行
(“the end”是在代码最后,就最后执行)。

执行结果:
Task 1 Finished
Task 2 Finished
Task 3 Finished
First exe, and then three’s async
All Task have been finished
the end

以上就是Swift中的DispatchGroup,其实呢,在Object-C中也有对应的方法。那就是
dispatch_group_enter
dispatch_group_leave
dispatch_group_wait
dispatch_group_notify
用法,跟Swift的一样,就不列代码了。

信号量
其实,上面的代码1的功能,还可以用其他方式来实现,例如信号量(Semaphore).
下面就用Semaphore来实现类似的功能。

需求:模拟从网络下载10张图片,一次最多允许下载3张。
func dealWithSemaphore() {

//创建一个最多允许三个访问的信号量
let semaphore = DispatchSemaphore(value: 3)
let queue = DispatchQueue(label: "my.queue.request")
let group = DispatchGroup()

//模拟下载10张图片
for i in 1...10 {

    queue.async(group: group) {

        semaphore.wait()

        print("正在下载第\(i) 张图片")

        Thread.sleep(forTimeInterval: 2.0)

        print("第\(i) 张图片下载完成")

        semaphore.signal()

    }
}

}
执行结果:
正在下载第1 张图片
第1 张图片下载完成
正在下载第2 张图片
第2 张图片下载完成
正在下载第3 张图片
第3 张图片下载完成
正在下载第4 张图片
第4 张图片下载完成
正在下载第5 张图片
第5 张图片下载完成
正在下载第6 张图片
第6 张图片下载完成
正在下载第7 张图片
第7 张图片下载完成
正在下载第8 张图片
第8 张图片下载完成
正在下载第9 张图片
第9 张图片下载完成
正在下载第10 张图片
第10 张图片下载完成

这样,就使用信号量完成了异步任务的处理。不过这里要注意,上面的信号量代码中依旧不能实现图片按次序依次下载的,只能限制最多下载数量,至于哪张图片先下、后下,没有规定了。

以上就是关于DispatchGroup和信号量的实践。

声明:文中观点不代表本站立场。本文传送门:https://eyangzhen.com/423493.html

联系我们
联系我们
分享本页
返回顶部