我是斯威夫特的新秀,有这样的误解
如何创建调度队列
有什么区别样本1
let backgroundQueue = DispatchQueue(label: "com.app.queue",
qos: .background,
target: nil)
backgroundQueue.async {
print("Dispatched to background queue")
}
样本2
let backgroundQueue = DispatchQueue.global()
backgroundQueue.async {
print("Dispatched to background queue")
}
据我所知,这两种方法都是相同的
或者例如这种方法
DispatchQueue.global(qos: .userInitiated).async {
print("user initiated task")
}
这是什么意思?
答案 0 :(得分:8)
您在第一个示例中创建的队列是您自己的自定义串行队列。虽然有点过时,但仍然相关,Concurrency Programming Guide说:
串行队列(也称为专用调度队列)按照将它们添加到队列的顺序一次执行一个任务。当前正在执行的任务在由调度队列管理的不同线程(可能因任务而异)上运行。串行队列通常用于同步对特定资源的访问。
您可以根据需要创建任意数量的串行队列,并且每个队列与所有其他队列同时运行。换句话说,如果您创建四个串行队列,则每个队列一次只执行一个任务,但最多可以同时执行四个任务,每个队列一个。
而后面的例子只是使用系统提供的并发全局队列:
并发队列(也称为一种全局调度队列)同时执行一个或多个任务,但任务仍按其添加到队列的顺序启动。当前正在执行的任务在由调度队列管理的不同线程上运行。在任何给定点执行的任务的确切数量是可变的,取决于系统条件。
现在,您现在可以创建自己的自定义并发队列,但全局队列只是为我们创建的并发队列。
那么,这对你意味着什么?
如果将块分派到串行队列(第一个示例),则任何时候只能运行一个块。这使得它在多线程应用程序中同步内存访问非常有用,但可以在需要后台队列的任何环境中使用,但是您希望调度块相对于该队列上的其他块串行(即顺序)运行
您在后面的示例中使用的全局队列是并发队列。这意味着如果将四个单独的任务分派给此全局队列,则这些块可以相互并发运行)。这是理想的,你不仅需要后台执行,而且不关心这些块是否也与其他调度块同时运行。
在后面的示例中,您正在访问全局队列,请认识到,因为这些是系统提供的,您对这些队列的交互有一些适度的限制,即:
您无法暂停全局队列;
您不能在全局队列中使用障碍;
但是,尽管如此,如果您只是在寻找一种简单的方法来调度块以在后台运行(并且您不关心这些调度的块是否在彼此同时运行),那么全局队列这是非常简单有效的方法。
顺便说一下,你的第二个例子(我假设你打算let backgroundQueue = DispatchQueue.global()
)和第三个例子之间的区别仅仅是在你的第三个例子中,你分配了明确的服务质量(qos),而在你的第二个例子中,你使用的是默认值。 FWIW,通常建议指定一个qos,以便操作系统可以优先考虑争用有限系统资源的线程。
答案 1 :(得分:0)
3之间差别不大。
示例1 会创建一个只有您的应用有权访问的队列。您还可以将其标签设置为com.app.queue
,这可以帮助您更轻松地进行调试。
示例2 无效Swift代码。我相信你的意思是:
let backgroundQueue = DispatchQueue.global(qos: .default) // or any other QoS
backgroundQueue.async {
print(backgroundQueue.label) // the label property tell you what queue it is
}
与示例1相同,接受您正在使用与其他应用程序共享的系统队列。
示例3 只是一种方便的方法(除了您指定的不同QoS):
DispatchQueue.global(qos: .userInitiated).async {
// you don't have any reference to the queue your code
// is running on, but most of times it's not needed
}
我编写的大多数代码都使用类似于Sample 3的代码。样本2最不常见。当您需要跨多个队列同步操作时,主要使用示例1。