串行队列应用场景
- 资源同步:当需要对共享资源进行同步访问,避免数据竞争时使用。例如,一个应用程序有一个全局的数据库操作对象,对数据库的读/写操作需要顺序执行,防止数据不一致。
// 创建串行队列
dispatch_queue_t serialQueue = dispatch_queue_create("com.example.serialQueue", DISPATCH_QUEUE_SERIAL);
// 在串行队列中执行数据库操作
dispatch_async(serialQueue, ^{
// 数据库写操作
});
dispatch_async(serialQueue, ^{
// 数据库读操作
});
- 顺序执行任务:某些任务依赖前序任务的结果,必须顺序执行。比如,先下载文件,然后解压文件,最后读取解压后的内容。
dispatch_async(serialQueue, ^{
// 下载文件
dispatch_async(serialQueue, ^{
// 解压文件
dispatch_async(serialQueue, ^{
// 读取解压后的内容
});
});
});
并行队列应用场景
- 计算密集型任务:当有多个独立的计算任务,且CPU有足够的核心来并行处理时,使用并行队列可以充分利用多核CPU的性能。例如,对一个数组中的每个元素进行复杂的数学运算。
// 创建并行队列
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
NSMutableArray *numbers = [NSMutableArray arrayWithArray:@[@1, @2, @3, @4, @5]];
[numbers enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
dispatch_async(concurrentQueue, ^{
NSNumber *number = obj;
// 复杂数学运算
NSNumber *result = @(number.integerValue * number.integerValue);
// 更新结果到数组等操作
});
}];
- I/O操作:如果有多个独立的I/O操作(如网络请求、文件读取等),并行队列可以同时发起这些操作,减少整体的等待时间。例如,同时从多个URL下载图片。
NSArray *imageURLs = @[@"url1", @"url2", @"url3"];
[imageURLs enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSString *urlString = obj;
dispatch_async(concurrentQueue, ^{
NSURL *url = [NSURL URLWithString:urlString];
NSData *imageData = [NSData dataWithContentsOfURL:url];
// 处理下载的图片数据
});
}];
选择原则
- 任务依赖关系:如果任务之间有严格的先后顺序,选择串行队列;如果任务相互独立,选择并行队列。
- 资源访问:对共享资源的操作,为避免数据竞争,选择串行队列;对无共享资源的独立任务,选择并行队列以提升性能。
- 任务类型:计算密集型和I/O密集型的独立任务适合并行队列,而涉及资源同步、顺序依赖的任务适合串行队列。