我对这个问题有疑问, 根据Apple的文件
并发 并发队列(也称为一种全局调度队列)同时执行一个或多个任务,但任务仍然按照它们添加到队列的顺序启动。当前正在执行的任务运行于由调度队列管理的不同线程。在任何给定点执行的任务的确切数量是可变的,取决于系统条件。 在iOS 5及更高版本中,您可以通过将DISPATCH_QUEUE_CONCURRENT指定为队列类型来自行创建并发调度队列。此外,还有四个预定义的全局并发队列供您的应用程序使用。有关如何获取全局并发队列的更多信息,请参阅获取全局并发调度队列。
我使用示例代码
进行测试 dispatch_queue_t concurrentQueue;
concurrentQueue = dispatch_queue_create("com.gcd.concurrentQueue",
DISPATCH_QUEUE_CONCURRENT);
dispatch_async(concurrentQueue, ^{
NSLog(@"First job ");
});
dispatch_async(concurrentQueue, ^{
NSLog(@"Second job");
});
dispatch_async(concurrentQueue, ^{
NSLog(@"Third job ");
});
但结果似乎不是它们的添加顺序,这是结果,
2015-06-03 18:36:38.114 GooglyPuff[58461:1110680] First job
2015-06-03 18:36:38.114 GooglyPuff[58461:1110682] Third job
2015-06-03 18:36:38.114 GooglyPuff[58461:1110679] Second job
所以我的问题是,不应该 第一第二第三 ?
欢迎任何建议,谢谢你的帮助。
答案 0 :(得分:3)
"并行"意味着他们在同一时间运行,并且不应该假设他们在任何特定时刻在任何特定时刻将完成任何进展。这就是并发的全部含义和含义:在一行代码和下一个并发操作之间 - 甚至在一行代码中 - 任何其他并发操作中的任何其他操作都可能发生。
因此,在回答您的特定问题时,这些任务可能已按照已知顺序启动,但这种情况发生得非常快,在此之后,他们的进度是交错的不可预知的。你的NSLog电话是这一进步的一部分;他们没有,也不能告诉你什么时候开始工作!
答案 1 :(得分:1)
文档是正确的 - 它们确实会按照您将它们添加到队列的顺序开始。一旦进入队列,它们将一个接一个地启动,但是在并发线程上。他们将完成的顺序取决于任务执行所需的时间。这是一个思想实验,想象你的代码是这样的:
dispatch_async(concurrentQueue, ^{
JobThatTakes_3_SecToExecute(); // Job 1 (3 seconds to execute)
});
dispatch_async(concurrentQueue, ^{
JobThatTakes_2_SecToExecute(); // Job 2 (2 seconds to execute)
});
dispatch_async(concurrentQueue, ^{
JobThatTakes_1_SecToExecute(); // Job 3 (1 second to execute)
});
与这些作业长度相比,进出队列的开销应该非常小,因此您可以期望它们在执行任务所需的时间内完成。在这种情况下,它们从作业3开始大约1秒钟,然后是2,然后是1.队列完成所需的总时间大约是作业1的长度,因为它需要花费最长的时间来执行。这很可爱,因为总时间主要取决于最长的工作,而不是工作的总和。但是,你对他们完成的顺序没有任何发言权,因为这是由任务持续时间决定的。
在此示例中将dispatch_async更改为dispatch_sync,队列将需要大约6秒钟才能完成。它们将按此顺序出现:作业1,2,然后是3.这将保证您的结果按照您想要的顺序排出,但需要更长的时间。
回到“任务仍然按照它们被添加到队列的顺序”开始对于并发队列来说,文档的意义重要性。如果您的工作受资源限制,这将是显而易见的。假设您在2 CPU机器上的并发队列中放置了大量长持续时间的任务。你不太可能在这里同时运行十几个CPU挂钩任务;有些人将不得不等待其他人跑。您将它们放入队列的顺序将决定在资源释放时谁将接下来运行。在您的示例中,任务的持续时间非常短,并且涉及控制台锁定(如Rob所述),因此队列/锁定开销可能会使您的期望变得混乱。
并发队列中执行顺序的另一个(可能更重要)原因是使用障碍时。你可能需要每N个其他任务运行某种任务,这就是障碍会派上用场的地方。执行的固定顺序将确保在N个任务同时完成后执行屏障,前提是您将屏障放在队列中的正确位置。