苹果公司在2009年发布的Grand Central Dispatch是为了管理同时运行的任务,对它们进行排队执行,并安排它们在后台未被占用的处理器上执行。
在Apache许可下发布的GCD包含一个开源库,通常被称为GCD或libdispatch。这个库在后台执行繁重的任务操作,保持主线程的顺利运行,并提供更快的响应时间。
GCD将任务作为一个不接受参数的空块或函数来工作。
我们将讨论GCD如何提供多线程和队列,以及探讨GCD用其技术和功能解决了哪些问题。
Grand Central Dispatch中的线程、多线程和队列
为了真正理解GCD,我们将回顾线程、多线程和队列。
线程
GCD中的线程包含主线程和后台线程;所有的任务都在这些线程上执行。尽可能地保持主线程的自由是很重要的,这样我们的用户界面才能保持快速和响应。任何繁重的任务都必须推送到后台线程。
多线程
因为CPU一次执行一个任务,我们可以使用多线程使CPU在不同的任务之间切换,让它同时执行多个任务。
多线程可以提高响应速度,减少执行多个任务时的滞后性,确保主线程不被打断。
队列
队列类似于公交线路。想象一下,人们在一个公共汽车站等待进入一辆公共汽车。队伍中的第一个人代表队列,进入公交车后离开队伍,这在编程中被称为先入先出。
有两种类型的队列。
- 串行队列,从第一个到最后一个,一次一个地执行任务
- 一个并发队列同时执行所有任务;任务根据正在执行的操作完成
就线程而言,并发队列在后台线程上工作,而主线程是串行队列。一个应用程序使用主队列来串行执行任务,并将繁重的任务分派给并发队列。这就是Grand Central Dispatch的作用。
Grand Central Dispatch能解决什么问题?
如果没有在后台线程上执行繁重任务的能力,任务就会以串行方式完成,从而减慢了性能。
但通过创建队列并将代码块放入队列,GCD将长而重的任务带到后台线程中执行。队列中等待执行的代码块被保存在一个闭包中。
GCD技术
GCD使用的技术对执行并发代码提供了全面的支持。
我们将回顾一些对iOS开发者有用的GCD技术,包括。
- 如何安排和管理任务与
DispatchQueue - 将任务作为一个单元进行分组和同步,用
DispatchGroup
DispatchQueue
这就是GCD通过将任务打包成一个块或函数来创建任务,并按照执行顺序或复杂程度将其放入队列。这可以使我们的任务队列保持有序,并有助于串行或并发地执行它们。
有三种类型的DispatchQueue 。
- 主队列是串行的,在主线程上运行,用于UI相关的操作
- 全局队列是并发队列,按优先级顺序执行任务
- 自定义队列是自定义的串行和并发队列
创建一个DispatchQueue ,内容如下。
let dispatchQueue = DispatchQueue(label: "myqueue")
然后我们可以通过添加下面的代码使任务同步或异步执行。
let dispatchQueue = DispatchQueue(label: "myqueue")
// Code executes synchronously
dispatchQueue.sync {
print("Do something synchronous")
}
// Code executes asynchronously
dispatchQueue.async {
print("Do something asynchronous")
}
如果我们只想同步执行我们的任务,我们添加以下内容。
let dispatchQueue = DispatchQueue(label: "myqueue")
// Task is synchronous
dispatchQueue.sync {
// Set timeinterval
Thread.sleep(forTimeInterval: 5)
print("Do something synchronous")
}
print("Do something")
// Do something synchronous
// Do something
注意,print("Do something") ,必须等待第一个任务完成。在这个例子中,第一个任务延迟5s,执行,然后进入到下一个代码。
如果我们需要我们的任务以异步方式运行,DispatchQueue 仍然可以帮助我们。当异步运行任务时,它们在自己的时间内完成,而主线程仍然同步执行。
let dispatchQueue = DispatchQueue(label: "myqueue")
dispatchQueue.async {
Thread.sleep(forTimeInterval: 1)
print("Do something asynchronous")
}
print("Do something")
// Do something
// Do something asynchronous
因为我们为"Do something asynchronous" 运行了dispatchQueue.async ,所以"Do something" 首先返回。
DispatchGroup
DispatchGroup 的主要目的是为了等待数据。当任务完成后,它们会等待整个组的任务完成,然后再转到下一个操作。因此,当我们有一组并发的任务时,当任务完成时,一个DispatchGroup 会通知我们。
当我们创建一个DispatchGroup ,我们可以创建一个自定义的并发和串行队列,其异步任务链接到同一个组。
如果我们想在每个组的任务完成时得到通知,我们可以使用group.notify ,它来自于我们之前声明的DispatchGroup 。
let group = DispatchGroup()
// Concurrent queue
let queue = DispatchQueue(label: "com.logrocket.concurrentqueue", attributes: .concurrent)
// Link the Queue to Group
queue.async(group: group) {
Thread.sleep(forTimeInterval: 3)
print("My first task")
}
// Serial queue
let queue2 = DispatchQueue(label: "com.logrocket.serialqueue", attributes: .serial)
// Link the Queue to Group
queue2.async(group: group) { // Group Linked
print("My second task")
}
// Notify us for completion of tasks on main thread.
group.notify(queue: DispatchQueue.main) {
Thread.sleep(forTimeInterval: 1)
print("All Concurrent task done")
}
print("Waiting for tasks")
/* Output:
My Task
Concurrent task done
Waiting for tasks
*/
这与semaphores的工作原理类似,但在我们的案例中,如果我们的任务没有接触到共享资源,我们必须使用DispatchGroup 。
结论
通过GCD,我们可以将管理线程的责任从主程序转移到操作系统。实现并发执行模式不再是开发人员必须负责的事情了。
The postGrand Central Dispatch tutorial appeared first onLogRocket Blog.