了解dispatch_async

我有这个代码的问题

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有什么好处?

我很困惑。 你能帮我理解一下吗?

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

例如,如果我正在从互联网下载文件,并且想要更新用户的下载进度,我将在优先级默认队列中运行下载,并在主队列中asynchronous更新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 }); }); 

所有DISPATCH_QUEUE_PRIORITY_X队列都是并发队列(这意味着它们可以一次执行多个任务),并且是FIFO,就是指定队列中的任务将以“先进先出”顺序开始执行。 这与主队列(来自dispatch_get_main_queue())相比,这是一个串行队列(任务将开始执行并按接收顺序完成执行)。

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

请注意,执行的顺序是以每个队列为基础的FIFO。 所以,如果你发送1000个dispatch_async()任务到四个不同的并发队列,平均分配它们并按顺序将它们发送到BACKGROUND,LOW,DEFAULT和HIGH(即你安排HIGH队列中的最后250个任务),很可能你看到的第一个任务就是在这个HIGH队列中,因为系统意味着这些任务需要尽快到达CPU。

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

根据苹果:

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

当您有多个可以并行运行的任务时,并发调度队列很有用。 并发队列仍然是一个队列,它按先进先出的顺序出队; 然而,并发队列可能在任何先前的任务完成之前将额外的任务出队。 并发队列在任何给定时刻执行的实际任务数量都是可变的,并且可以随应用程序中的条件变化而dynamic变化。 许多因素会影响并发队列执行的任务数量,包括可用内核数量,其他进程执行的工作量以及其他串行调度队列中任务的数量和优先级。

基本上,如果将这1000个dispatch_async()块发送到DEFAULT,HIGH,LOW或BACKGROUND队列,它们都将按照您发送的顺序开始执行。 但是,较短的任务可能会在较长的任务之前完 这背后的原因是,如果有可用的CPU核心,或者当前的队列任务正在执行非计算密集型工作(因此使得系统认为它可以并行调度额外的任务,而不pipe核心数量是多less)。

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

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

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

Swift版本

这是David的Objective-C答案的Swift版本。 您使用全局队列在后台运行事务,并使用主队列来更新UI。

Swift 3

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