串行队列实际上确保添加到队列中执行的第一个块在第二个块执行之前完成。
-(void)testSerialQueue
{
dispatch_queue_t serialQueue = dispatch_queue_create("com.serial.queue", DISPATCH_QUEUE_SERIAL);
dispatch_async(serialQueue, ^{
[self countTo100];
});
dispatch_async(serialQueue, ^{
[self countFrom200To400];
});
dispatch_async(serialQueue, ^{
[self countFrom400To500];
});
}
- (void)countTo100
{
for (int i = 0; i < 100; i++) {
NSLog(@"%d", i);
}
}
- (void)countFrom200To400
{
for (int i = 200; i < 400; i++) {
NSLog(@"%d", i);
}
}
- (void)countFrom400To500
{
for (int i = 400; i < 500; i++) {
NSLog(@"%d", i);
}
}
如果您从上方查看日志,它将首先从 0 .. 100 依次打印,然后是 200 .. 400 和 400 .. 500。
现在,考虑以下 sn-p,您可以在并发块中执行每个方法,例如,
-(void)testSerialQueue
{
dispatch_queue_t serialQueue = dispatch_queue_create("com.serial.queue", DISPATCH_QUEUE_SERIAL);
dispatch_async(serialQueue, ^{
[self countTo100];
});
dispatch_async(serialQueue, ^{
[self countFrom200To400];
});
dispatch_async(serialQueue, ^{
[self countFrom400To500];
});
}
- (void)countTo100
{
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(concurrentQueue, ^{
for (int i = 0; i < 100; i++) {
NSLog(@"%d", i);
}
});
}
- (void)countFrom200To400
{
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(concurrentQueue, ^{
for (int i = 200; i < 400; i++) {
NSLog(@"%d", i);
}
});
}
- (void)countFrom400To500
{
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(concurrentQueue, ^{
for (int i = 400; i < 500; i++) {
NSLog(@"%d", i);
}
});
}
在这里,您在串行队列中添加了所有方法,但方法本身在并发块中运行。因此,在这种情况下,结果是随机的。你也可以像这样使用 dispatch_group 序列化它,
-(void)testSerialQueue
{
dispatch_queue_t serialQueue = dispatch_queue_create("com.serial.queue", DISPATCH_QUEUE_SERIAL);
self.group = dispatch_group_create();
dispatch_async(serialQueue, ^{
[self countTo100];
});
dispatch_async(serialQueue, ^{
[self countFrom200To400];
});
dispatch_async(serialQueue, ^{
[self countFrom400To500];
});
}
- (void)countTo100
{
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_enter(self.group);
dispatch_async(concurrentQueue, ^{
for (int i = 0; i < 100; i++) {
NSLog(@"%d", i);
}
dispatch_group_leave(self.group);
});
dispatch_group_wait(self.group, DISPATCH_TIME_FOREVER);
}
- (void)countFrom200To400
{
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_enter(self.group);
dispatch_async(concurrentQueue, ^{
for (int i = 200; i < 400; i++) {
NSLog(@"%d", i);
}
dispatch_group_leave(self.group);
});
dispatch_group_wait(self.group, DISPATCH_TIME_FOREVER);
}
- (void)countFrom400To500
{
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_enter(self.group);
dispatch_async(concurrentQueue, ^{
for (int i = 400; i < 500; i++) {
NSLog(@"%d", i);
}
dispatch_group_leave(self.group);
});
dispatch_group_wait(self.group, DISPATCH_TIME_FOREVER);
}
在这里,您将再次看到它有序地打印日志。因此,dispatch_group 用于序列化并发操作。此时您可能更愿意删除 serialQueue 中的 dispatch_async。
现在,操作队列,让我们看一个简单的例子,
-(void)testSerialQueue
{
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount = 1;
NSBlockOperation *operation1 = [[NSBlockOperation alloc] init];
NSBlockOperation *operation2 = [[NSBlockOperation alloc] init];
NSBlockOperation *operation3 = [[NSBlockOperation alloc] init];
[operation1 addExecutionBlock:^{
[self countTo100];
}];
[operation2 addExecutionBlock:^{
[self countFrom200To400];
}];
[operation3 addExecutionBlock:^{
[self countFrom400To500];
}];
}
- (void)countTo100
{
for (int i = 0; i < 100; i++) {
NSLog(@"%d", i);
}
}
- (void)countFrom200To400
{
for (int i = 200; i < 400; i++) {
NSLog(@"%d", i);
}
}
- (void)countFrom400To500
{
for (int i = 400; i < 500; i++) {
NSLog(@"%d", i);
}
}
count 方法被添加到 NSOperationQueue 中,maxConcurrentOperation 为“1”,现在更像是一个串行队列。每个方法都不会产生其他一些队列,因此计数在同一个串行队列上执行。所以,它们都打印有序。
现在,让我们看一个模拟您的案例的示例。
-(void)testSerialQueue
{
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount = 1;
NSBlockOperation *operation1 = [[NSBlockOperation alloc] init];
NSBlockOperation *operation2 = [[NSBlockOperation alloc] init];
NSBlockOperation *operation3 = [[NSBlockOperation alloc] init];
[operation1 addExecutionBlock:^{
[self countTo100];
}];
[operation2 addExecutionBlock:^{
[self countFrom200To400];
}];
[operation3 addExecutionBlock:^{
[self countFrom400To500];
}];
}
- (void)countTo100
{
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(concurrentQueue, ^{
for (int i = 0; i < 100; i++) {
NSLog(@"%d", i);
}
});
}
- (void)countFrom200To400
{
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(concurrentQueue, ^{
for (int i = 200; i < 400; i++) {
NSLog(@"%d", i);
}
});
}
- (void)countFrom400To500
{
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(concurrentQueue, ^{
for (int i = 400; i < 500; i++) {
NSLog(@"%d", i);
}
});
}
在这个用例中,您将操作添加到 NSOperationQueue(即串行队列),但同样,各个方法在其他一些并发队列中运行。所以,执行顺序是相当随机的。现在,您可以使用 dispatch_group 解决这个问题,就像我们之前对串行队列所做的那样。
-(void)testSerialQueue
{
self.group = dispatch_group_create();
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount = 1;
NSBlockOperation *operation1 = [[NSBlockOperation alloc] init];
NSBlockOperation *operation2 = [[NSBlockOperation alloc] init];
NSBlockOperation *operation3 = [[NSBlockOperation alloc] init];
[operation1 addExecutionBlock:^{
[self countTo100];
}];
[operation2 addExecutionBlock:^{
[self countFrom200To400];
}];
[operation3 addExecutionBlock:^{
[self countFrom400To500];
}];
}
- (void)countTo100
{
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_enter(self.group);
dispatch_async(concurrentQueue, ^{
for (int i = 0; i < 100; i++) {
NSLog(@"%d", i);
}
dispatch_group_leave(self.group);
});
dispatch_group_wait(self.group, DISPATCH_TIME_FOREVER);
}
- (void)countFrom200To400
{
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_enter(self.group);
dispatch_async(concurrentQueue, ^{
for (int i = 200; i < 400; i++) {
NSLog(@"%d", i);
}
dispatch_group_leave(self.group);
});
dispatch_group_wait(self.group, DISPATCH_TIME_FOREVER);
}
- (void)countFrom400To500
{
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_enter(self.group);
dispatch_async(concurrentQueue, ^{
for (int i = 400; i < 500; i++) {
NSLog(@"%d", i);
}
dispatch_group_leave(self.group);
});
dispatch_group_wait(self.group, DISPATCH_TIME_FOREVER);
}
现在,您将看到计数再次变得有序。这是因为dispatch_group,它一直等到每个异步任务完成。
对于您的特定用例,您可以使用循环来调用某些方法,像这样创建 NSInvocationOperation,
-(void)testSerialQueue
{
self.group = dispatch_group_create();
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount = 1;
NSArray *selectors = @[@"countTo100", @"countFrom200To400", @"countFrom400To500"];
for (NSString *selector in selectors) {
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self
selector:NSSelectorFromString(selector)
object:nil];
[queue addOperation:operation];
}
}
- (void)countTo100
{
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_enter(self.group);
dispatch_async(concurrentQueue, ^{
for (int i = 0; i < 100; i++) {
NSLog(@"%d", i);
}
dispatch_group_leave(self.group);
});
dispatch_group_wait(self.group, DISPATCH_TIME_FOREVER);
}
- (void)countFrom200To400
{
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_enter(self.group);
dispatch_async(concurrentQueue, ^{
for (int i = 200; i < 400; i++) {
NSLog(@"%d", i);
}
dispatch_group_leave(self.group);
});
dispatch_group_wait(self.group, DISPATCH_TIME_FOREVER);
}
- (void)countFrom400To500
{
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_enter(self.group);
dispatch_async(concurrentQueue, ^{
for (int i = 400; i < 500; i++) {
NSLog(@"%d", i);
}
dispatch_group_leave(self.group);
});
dispatch_group_wait(self.group, DISPATCH_TIME_FOREVER);
}