在 Grand Central Dispatch 中,当使用 serial
时,调度程序如何处理不同的队列( concurrent
和 dispatch_sync
)函数和 dispatch_async
功能?
最佳答案
首先,我们需要两种类型的队列:一种串行和一种并发:
dispatch_queue_t serialQueue =
dispatch_queue_create("com.matteogobbi.dispex.serial_queue", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t concurrentQueue =
dispatch_queue_create("com.matteogobbi.dispex.concurrent_queue", DISPATCH_QUEUE_CONCURRENT);
因此,我们可以从第一个实验开始,使用串行队列和所有dispatch_async
函数将我们的 block 添加到队列中:
/* Dispatch async with serial queue */
NSLog(@"\n\nDISPATCH: Async - QUEUE: Serial");
NSLog(@"block 1 added");
dispatch_async(serialQueue, ^{
NSLog(@"block 1");
});
NSLog(@"block 2 added");
dispatch_async(serialQueue, ^{
NSLog(@"block 2");
});
NSLog(@"block 3 added");
dispatch_async(serialQueue, ^{
NSLog(@"block 3");
});
NSLog(@"block 4 added");
dispatch_async(serialQueue, ^{
NSLog(@"block 4");
});
NSLog(@"block 5 added");
dispatch_async(serialQueue, ^{
NSLog(@"block 5");
});
NSLog(@"block 6 added");
dispatch_async(serialQueue, ^{
NSLog(@"block 6");
});
NSLog(@"block 7 added");
dispatch_async(serialQueue, ^{
NSLog(@"block 7");
});
NSLog(@"block 8 added");
dispatch_async(serialQueue, ^{
NSLog(@"block 8");
});
NSLog(@"block 9 added");
dispatch_async(serialQueue, ^{
NSLog(@"block 9");
});
NSLog(@"block 10 added");
dispatch_async(serialQueue, ^{
NSLog(@"block 10");
});
NSLog(@"ALL BLOCK ADDED TO THE QUEUE --> FUNCTION RETURNED");
DISPATCH: Async - QUEUE: Serial
2014-04-08 14:43:16.468 dispex[4346:60b] block 1 added
2014-04-08 14:43:16.468 dispex[4346:60b] block 2 added
2014-04-08 14:43:16.468 dispex[4346:1303] block 1
2014-04-08 14:43:16.469 dispex[4346:1303] block 2
2014-04-08 14:43:16.468 dispex[4346:60b] block 3 added
2014-04-08 14:43:16.469 dispex[4346:1303] block 3
2014-04-08 14:43:16.469 dispex[4346:60b] block 4 added
2014-04-08 14:43:16.469 dispex[4346:1303] block 4
2014-04-08 14:43:16.469 dispex[4346:60b] block 5 added
2014-04-08 14:43:16.470 dispex[4346:60b] block 6 added
2014-04-08 14:43:16.470 dispex[4346:1303] block 5
2014-04-08 14:43:16.471 dispex[4346:60b] block 7 added
2014-04-08 14:43:16.471 dispex[4346:1303] block 6
2014-04-08 14:43:16.471 dispex[4346:1303] block 7
2014-04-08 14:43:16.471 dispex[4346:60b] block 8 added
2014-04-08 14:43:16.471 dispex[4346:1303] block 8
2014-04-08 14:43:16.471 dispex[4346:60b] block 9 added
2014-04-08 14:43:16.472 dispex[4346:60b] block 10 added
2014-04-08 14:43:16.472 dispex[4346:1303] block 9
2014-04-08 14:43:16.472 dispex[4346:1303] block 10
2014-04-08 14:43:16.472 dispex[4346:60b] ALL BLOCK ADDED TO THE QUEUE --> FUNCTION RETURNED
如您所见, block 已添加到队列中,但同时调度程序开始执行它们。这是dispatcher_async
函数的一个特性,即将 block 添加到队列中而不等待它们完成执行。换句话说,如果您在函数中使用dispatch_async,该函数会立即返回,同时该 block 正在执行。这非常有用!在此示例中,我使用 NSLog 来报告 block 何时添加到队列中,因此这确实会导致执行速度变慢并导致日志
ALL BLOCK ADDED
在最后。但正如我们稍后将看到的,如果没有日志,它将被写在开头。由于我们使用的是串行队列,因此 block 按照添加的顺序执行。
下一个:
/* Just wait before begin with the next test */
dispatch_group_wait(group_async_serial, DISPATCH_TIME_FOREVER);
/* Dispatch sync with serial queue */
NSLog(@"\n\nDISPATCH: Sync - QUEUE: Serial");
NSLog(@"block 1 added");
dispatch_sync(serialQueue, ^{
NSLog(@"block 1");
});
NSLog(@"block 2 added");
dispatch_sync(serialQueue, ^{
NSLog(@"block 2");
});
NSLog(@"block 3 added");
dispatch_sync(serialQueue, ^{
NSLog(@"block 3");
});
NSLog(@"block 4 added");
dispatch_sync(serialQueue, ^{
NSLog(@"block 4");
});
NSLog(@"block 5 added");
dispatch_sync(serialQueue, ^{
NSLog(@"block 5");
});
NSLog(@"block 6 added");
dispatch_sync(serialQueue, ^{
NSLog(@"block 6");
});
NSLog(@"block 7 added");
dispatch_sync(serialQueue, ^{
NSLog(@"block 7");
});
NSLog(@"block 8 added");
dispatch_sync(serialQueue, ^{
NSLog(@"block 8");
});
NSLog(@"block 9 added");
dispatch_sync(serialQueue, ^{
NSLog(@"block 9");
});
NSLog(@"block 10 added");
dispatch_sync(serialQueue, ^{
NSLog(@"block 10");
});
NSLog(@"ALL BLOCK ADDED TO THE QUEUE --> FUNCTION RETURNED");
DISPATCH: Sync - QUEUE: Serial
2014-04-08 14:43:16.473 dispex[4346:60b] block 1 added
2014-04-08 14:43:16.474 dispex[4346:60b] block 1
2014-04-08 14:43:16.474 dispex[4346:60b] block 2 added
2014-04-08 14:43:16.474 dispex[4346:60b] block 2
2014-04-08 14:43:16.475 dispex[4346:60b] block 3 added
2014-04-08 14:43:16.475 dispex[4346:60b] block 3
2014-04-08 14:43:16.475 dispex[4346:60b] block 4 added
2014-04-08 14:43:16.475 dispex[4346:60b] block 4
2014-04-08 14:43:16.476 dispex[4346:60b] block 5 added
2014-04-08 14:43:16.476 dispex[4346:60b] block 5
2014-04-08 14:43:16.476 dispex[4346:60b] block 6 added
2014-04-08 14:43:16.477 dispex[4346:60b] block 6
2014-04-08 14:43:16.477 dispex[4346:60b] block 7 added
2014-04-08 14:43:16.477 dispex[4346:60b] block 7
2014-04-08 14:43:16.477 dispex[4346:60b] block 8 added
2014-04-08 14:43:16.478 dispex[4346:60b] block 8
2014-04-08 14:43:16.478 dispex[4346:60b] block 9 added
2014-04-08 14:43:16.478 dispex[4346:60b] block 9
2014-04-08 14:43:16.479 dispex[4346:60b] block 10 added
2014-04-08 14:43:16.479 dispex[4346:60b] block 10
2014-04-08 14:43:16.479 dispex[4346:60b] ALL BLOCK ADDED TO THE QUEUE --> FUNCTION RETURNED
在此示例中,我们将 dispatch_sync
函数与串行队列结合使用。很容易看出,当前一个 block 执行完毕时,所有 block 都会被添加。这是dispatch_sync
的一个特性。换句话说,直到 block 执行完毕后,该函数才会返回。由于这是一个串行队列,因此这里的顺序也受到尊重。
下一个:
/* Dispatch async with concurrent queue */
NSLog(@"\n\nDISPATCH: Async - QUEUE: Concurrent");
dispatch_group_t group_async_concurrent = dispatch_group_create();
dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
NSLog(@"block 1");
});
dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
NSLog(@"block 2");
});
dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
NSLog(@"block 3");
});
dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
NSLog(@"block 4");
});
dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
NSLog(@"block 5");
});
dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
NSLog(@"block 6");
});
dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
NSLog(@"block 7");
});
dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
NSLog(@"block 8");
});
dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
NSLog(@"block 9");
});
dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
NSLog(@"block 10");
});
dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
NSLog(@"block 11");
});
dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
NSLog(@"block 12");
});
dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
NSLog(@"block 13");
});
dispatch_group_async(group_async_concurrent, concurrentQueue, ^{
NSLog(@"block 14");
});
NSLog(@"ALL BLOCK ADDED TO THE QUEUE --> FUNCTION RETURNED");
DISPATCH: Async - QUEUE: Concurrent
2014-04-08 14:43:16.480 dispex[4346:60b] ALL BLOCK ADDED TO THE QUEUE --> FUNCTION RETURNED
2014-04-08 14:43:16.480 dispex[4346:1303] block 1
2014-04-08 14:43:16.480 dispex[4346:3503] block 2
2014-04-08 14:43:16.480 dispex[4346:3603] block 3
2014-04-08 14:43:16.480 dispex[4346:3803] block 5
2014-04-08 14:43:16.480 dispex[4346:3703] block 4
2014-04-08 14:43:16.480 dispex[4346:3903] block 6
2014-04-08 14:43:16.480 dispex[4346:3a03] block 7
2014-04-08 14:43:16.480 dispex[4346:3b03] block 8
2014-04-08 14:43:16.482 dispex[4346:1303] block 9
2014-04-08 14:43:16.483 dispex[4346:3503] block 10
2014-04-08 14:43:16.483 dispex[4346:3803] block 12
2014-04-08 14:43:16.483 dispex[4346:3703] block 13
2014-04-08 14:43:16.483 dispex[4346:3903] block 14
2014-04-08 14:43:16.483 dispex[4346:3603] block 11
正如我之前所说,这里我展示了 dispatch_async
如何使用并发队列工作。
这真的很有趣,因为没有 NSLog 显示何时添加 block ,您可以看到在执行第一个 block 之前如何添加所有 block 。这种行为不是恒定的。 可能会发生 block1 被执行后,在 dispatch_async
完成后立即将所有 block 添加到队列中,然后继续执行其他 block 。另一件需要注意的事情是, block 是并发执行的,因此它们不遵守添加顺序,而且这种行为不是恒定的,而是取决于 CPU 使用率、性能和许多其他因素。
下一个:
/* Just wait before begin with the next test */
dispatch_group_wait(group_async_concurrent, DISPATCH_TIME_FOREVER);
/* Dispatch sync with concurrent queue */
NSLog(@"\n\nDISPATCH: Sync - QUEUE: Concurrent");
NSLog(@"block 1 added");
dispatch_sync(concurrentQueue, ^{
NSLog(@"block 1");
});
NSLog(@"block 2 added");
dispatch_sync(concurrentQueue, ^{
NSLog(@"block 2");
});
NSLog(@"block 3 added");
dispatch_sync(concurrentQueue, ^{
NSLog(@"block 3");
});
NSLog(@"block 4 added");
dispatch_sync(concurrentQueue, ^{
NSLog(@"block 4");
});
NSLog(@"block 5 added");
dispatch_sync(concurrentQueue, ^{
NSLog(@"block 5");
});
NSLog(@"block 6 added");
dispatch_sync(concurrentQueue, ^{
NSLog(@"block 6");
});
NSLog(@"block 7 added");
dispatch_sync(concurrentQueue, ^{
NSLog(@"block 7");
});
NSLog(@"block 8 added");
dispatch_sync(concurrentQueue, ^{
NSLog(@"block 8");
});
NSLog(@"block 9 added");
dispatch_sync(concurrentQueue, ^{
NSLog(@"block 9");
});
NSLog(@"block 10 added");
dispatch_sync(concurrentQueue, ^{
NSLog(@"block 10");
});
NSLog(@"ALL BLOCK ADDED TO THE QUEUE --> FUNCTION RETURNED");
DISPATCH: Sync - QUEUE: Concurrent
2014-04-08 14:43:16.486 dispex[4346:60b] block 1 added
2014-04-08 14:43:16.486 dispex[4346:60b] block 1
2014-04-08 14:43:16.487 dispex[4346:60b] block 2 added
2014-04-08 14:43:16.487 dispex[4346:60b] block 2
2014-04-08 14:43:16.487 dispex[4346:60b] block 3 added
2014-04-08 14:43:16.488 dispex[4346:60b] block 3
2014-04-08 14:43:16.488 dispex[4346:60b] block 4 added
2014-04-08 14:43:16.488 dispex[4346:60b] block 4
2014-04-08 14:43:16.489 dispex[4346:60b] block 5 added
2014-04-08 14:43:16.489 dispex[4346:60b] block 5
2014-04-08 14:43:16.489 dispex[4346:60b] block 6 added
2014-04-08 14:43:16.489 dispex[4346:60b] block 6
2014-04-08 14:43:16.490 dispex[4346:60b] block 7 added
2014-04-08 14:43:16.490 dispex[4346:60b] block 7
2014-04-08 14:43:16.490 dispex[4346:60b] block 8 added
2014-04-08 14:43:16.491 dispex[4346:60b] block 8
2014-04-08 14:43:16.491 dispex[4346:60b] block 9 added
2014-04-08 14:43:16.491 dispex[4346:60b] block 9
2014-04-08 14:43:16.492 dispex[4346:60b] block 10 added
2014-04-08 14:43:16.492 dispex[4346:60b] block 10
2014-04-08 14:43:16.492 dispex[4346:60b] ALL BLOCK ADDED TO THE QUEUE --> FUNCTION RETURNED
最后,我们在这里使用了 dispatch_sync
和并发队列。它看起来完全等于同步/串行对。在这种情况下就是这样。这种行为的原因是,如果队列是并发的,它没有其他 block 要执行,因为我们正在使用同步调度程序,因此它会等待添加下一个 block ,直到实际执行完毕为止。如果我们还使用 dispatch_async
将 block 添加到队列中,这种类型的对(同步/并发)非常有用。在这种情况下,调度程序可以将其他 block 添加到要执行的队列中。
希望这个迷你演示有用;)
干杯!
关于ios - 当同步/异步与串行/并发队列混合时,调度程序如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22940154/