MST

星途 面试题库

面试题:Objective-C多线程编程中GCD队列的性能差异

在Objective-C多线程编程里,使用Grand Central Dispatch(GCD)时,串行队列和并行队列在性能优化方面有哪些不同的应用场景?请举例说明如何合理选择这两种队列来提升程序性能。
17.0万 热度难度
编程语言Objective-C

知识考点

AI 面试

面试题答案

一键面试

串行队列应用场景

  1. 资源同步:当需要对共享资源进行同步访问,避免数据竞争时使用。例如,一个应用程序有一个全局的数据库操作对象,对数据库的读/写操作需要顺序执行,防止数据不一致。
// 创建串行队列
dispatch_queue_t serialQueue = dispatch_queue_create("com.example.serialQueue", DISPATCH_QUEUE_SERIAL);
// 在串行队列中执行数据库操作
dispatch_async(serialQueue, ^{
    // 数据库写操作
});
dispatch_async(serialQueue, ^{
    // 数据库读操作
});
  1. 顺序执行任务:某些任务依赖前序任务的结果,必须顺序执行。比如,先下载文件,然后解压文件,最后读取解压后的内容。
dispatch_async(serialQueue, ^{
    // 下载文件
    dispatch_async(serialQueue, ^{
        // 解压文件
        dispatch_async(serialQueue, ^{
            // 读取解压后的内容
        });
    });
});

并行队列应用场景

  1. 计算密集型任务:当有多个独立的计算任务,且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);
        // 更新结果到数组等操作
    });
}];
  1. 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];
        // 处理下载的图片数据
    });
}];

选择原则

  1. 任务依赖关系:如果任务之间有严格的先后顺序,选择串行队列;如果任务相互独立,选择并行队列。
  2. 资源访问:对共享资源的操作,为避免数据竞争,选择串行队列;对无共享资源的独立任务,选择并行队列以提升性能。
  3. 任务类型:计算密集型和I/O密集型的独立任务适合并行队列,而涉及资源同步、顺序依赖的任务适合串行队列。