我对这段代码有疑问

dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    NSData* data = [NSData dataWithContentsOfURL: 
      kLatestKivaLoansURL];
    [self performSelectorOnMainThread:@selector(fetchedData:) 
      withObject:data waitUntilDone:YES];
});

这段代码的第一个参数是

dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) 

我们是否要求这段代码在全局队列上执行串行任务,其定义本身是返回给定优先级的全局并发队列?

使用dispatch_get_global_queue而不是主队列的优点是什么?

我很困惑。你能帮我更好地理解这个吗?


当前回答

所有DISPATCH_QUEUE_PRIORITY_X队列都是并发队列(意味着它们可以同时执行多个任务),并且在给定队列中的任务将以“先入先出”的顺序开始执行的意义上是FIFO。这与主队列(来自dispatch_get_main_queue())相比,主队列是一个串行队列(任务将按照接收到的顺序开始执行和结束执行)。

因此,如果您向DISPATCH_QUEUE_PRIORITY_DEFAULT发送1000个dispatch_async()块,这些任务将按照您发送到队列中的顺序开始执行。HIGH、LOW和BACKGROUND队列也是如此。发送到这些队列中的任何内容都在备用线程上后台执行,远离主应用程序线程。因此,这些队列适合执行后台下载、压缩、计算等任务。

注意,执行顺序是基于每个队列的FIFO。因此,如果你发送1000个dispatch_async()任务到四个不同的并发队列,平均分配它们,并将它们依次发送到BACKGROUND, LOW, DEFAULT和HIGH队列(即你将最后250个任务安排在HIGH队列上),很可能你看到的第一个开始的任务将在HIGH队列上,因为系统已经接受了你的暗示,这些任务需要尽快到达CPU。

还要注意,我说的是“将按顺序开始执行”,但请记住,作为并发队列,根据每个任务的时间长度,事情不一定按顺序完成执行。

苹果公司表示:

https://developer.apple.com/library/content/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html

A concurrent dispatch queue is useful when you have multiple tasks that can run in parallel. A concurrent queue is still a queue in that it dequeues tasks in a first-in, first-out order; however, a concurrent queue may dequeue additional tasks before any previous tasks finish. The actual number of tasks executed by a concurrent queue at any given moment is variable and can change dynamically as conditions in your application change. Many factors affect the number of tasks executed by the concurrent queues, including the number of available cores, the amount of work being done by other processes, and the number and priority of tasks in other serial dispatch queues.

基本上,如果你将这1000个dispatch_async()块发送到DEFAULT、HIGH、LOW或BACKGROUND队列,它们将按照你发送它们的顺序开始执行。然而,短时间的任务可能比长时间的任务先完成。这背后的原因是是否有可用的CPU内核,或者当前队列任务是否正在执行计算上不密集的工作(从而使系统认为它可以并行分派额外的任务,而不管内核数量)。

并发级别完全由系统处理,并基于系统负载和其他内部确定的因素。这就是Grand Central Dispatch (dispatch_async()系统)的美妙之处——您只需将工作单元作为代码块,为它们设置优先级(基于您选择的队列),然后让系统处理其余的工作。

所以回答你上面的问题:你是部分正确的。您正在“要求该代码”以指定的优先级在全局并发队列上执行并发任务。块中的代码将在后台执行,任何额外的(类似的)代码将根据系统对可用资源的评估潜在地并行执行。

另一方面,“主队列”(from dispatch_get_main_queue())是一个串行队列(不是并发队列)。发送到主队列的任务将始终按顺序执行,并始终按顺序完成。这些任务也将在UI线程上执行,所以它适合用进度消息、完成通知等更新你的UI。

其他回答

所有DISPATCH_QUEUE_PRIORITY_X队列都是并发队列(意味着它们可以同时执行多个任务),并且在给定队列中的任务将以“先入先出”的顺序开始执行的意义上是FIFO。这与主队列(来自dispatch_get_main_queue())相比,主队列是一个串行队列(任务将按照接收到的顺序开始执行和结束执行)。

因此,如果您向DISPATCH_QUEUE_PRIORITY_DEFAULT发送1000个dispatch_async()块,这些任务将按照您发送到队列中的顺序开始执行。HIGH、LOW和BACKGROUND队列也是如此。发送到这些队列中的任何内容都在备用线程上后台执行,远离主应用程序线程。因此,这些队列适合执行后台下载、压缩、计算等任务。

注意,执行顺序是基于每个队列的FIFO。因此,如果你发送1000个dispatch_async()任务到四个不同的并发队列,平均分配它们,并将它们依次发送到BACKGROUND, LOW, DEFAULT和HIGH队列(即你将最后250个任务安排在HIGH队列上),很可能你看到的第一个开始的任务将在HIGH队列上,因为系统已经接受了你的暗示,这些任务需要尽快到达CPU。

还要注意,我说的是“将按顺序开始执行”,但请记住,作为并发队列,根据每个任务的时间长度,事情不一定按顺序完成执行。

苹果公司表示:

https://developer.apple.com/library/content/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html

A concurrent dispatch queue is useful when you have multiple tasks that can run in parallel. A concurrent queue is still a queue in that it dequeues tasks in a first-in, first-out order; however, a concurrent queue may dequeue additional tasks before any previous tasks finish. The actual number of tasks executed by a concurrent queue at any given moment is variable and can change dynamically as conditions in your application change. Many factors affect the number of tasks executed by the concurrent queues, including the number of available cores, the amount of work being done by other processes, and the number and priority of tasks in other serial dispatch queues.

基本上,如果你将这1000个dispatch_async()块发送到DEFAULT、HIGH、LOW或BACKGROUND队列,它们将按照你发送它们的顺序开始执行。然而,短时间的任务可能比长时间的任务先完成。这背后的原因是是否有可用的CPU内核,或者当前队列任务是否正在执行计算上不密集的工作(从而使系统认为它可以并行分派额外的任务,而不管内核数量)。

并发级别完全由系统处理,并基于系统负载和其他内部确定的因素。这就是Grand Central Dispatch (dispatch_async()系统)的美妙之处——您只需将工作单元作为代码块,为它们设置优先级(基于您选择的队列),然后让系统处理其余的工作。

所以回答你上面的问题:你是部分正确的。您正在“要求该代码”以指定的优先级在全局并发队列上执行并发任务。块中的代码将在后台执行,任何额外的(类似的)代码将根据系统对可用资源的评估潜在地并行执行。

另一方面,“主队列”(from dispatch_get_main_queue())是一个串行队列(不是并发队列)。发送到主队列的任务将始终按顺序执行,并始终按顺序完成。这些任务也将在UI线程上执行,所以它适合用进度消息、完成通知等更新你的UI。

在主队列之上使用默认队列的主要原因是在后台运行任务。

例如,如果我正在从互联网上下载一个文件,我想要更新用户下载的进度,我将在优先级默认队列中运行下载,并异步更新主队列中的UI。

dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
    //Background Thread
    dispatch_async(dispatch_get_main_queue(), ^(void){
        //Run UI Updates
    });
});

斯威夫特版本

这是David Objective-C回答的Swift版本。你用全局队列在后台运行,用主队列更新UI。

DispatchQueue.global(qos: .background).async {
    
    // Background Thread
    
    DispatchQueue.main.async {
        // Run UI Updates
    }
}