MST
星途 面试题库

面试题:Objective-C的GCD多线程编程之同步异步操作

假设有一个复杂的业务逻辑,需要先在后台线程进行数据下载,下载完成后在主线程更新UI,同时有一些辅助计算任务可以并行处理。请用Objective-C结合GCD实现这个逻辑,并解释为什么要这样安排同步和异步操作。
29.3万 热度难度
编程语言Objective-C

知识考点

AI 面试

面试题答案

一键面试
#import <UIKit/UIKit.h>
#import <dispatch/dispatch.h>

@interface ViewController : UIViewController

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 后台线程进行数据下载
    dispatch_queue_t downloadQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(downloadQueue, ^{
        // 模拟数据下载
        NSData *downloadedData = [self downloadData];
        
        // 并行处理辅助计算任务
        dispatch_group_t group = dispatch_group_create();
        dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        
        dispatch_group_async(group, concurrentQueue, ^{
            [self performAuxiliaryCalculation1];
        });
        
        dispatch_group_async(group, concurrentQueue, ^{
            [self performAuxiliaryCalculation2];
        });
        
        dispatch_group_notify(group, dispatch_get_main_queue(), ^{
            // 回到主线程更新UI
            [self updateUIWithData:downloadedData];
        });
    });
}

- (NSData *)downloadData {
    // 模拟数据下载
    sleep(2);
    return [@"Downloaded Data" dataUsingEncoding:NSUTF8StringEncoding];
}

- (void)performAuxiliaryCalculation1 {
    // 模拟辅助计算1
    sleep(1);
    NSLog(@"Auxiliary Calculation 1 completed");
}

- (void)performAuxiliaryCalculation2 {
    // 模拟辅助计算2
    sleep(1);
    NSLog(@"Auxiliary Calculation 2 completed");
}

- (void)updateUIWithData:(NSData *)data {
    NSString *text = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    self.view.backgroundColor = [UIColor whiteColor];
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(100, 100, 200, 50)];
    label.text = text;
    [self.view addSubview:label];
}

@end

同步和异步操作安排原因解释

  1. 数据下载在后台线程:数据下载通常会涉及网络请求或磁盘I/O操作,这些操作是耗时的。如果在主线程进行,会阻塞主线程,导致UI卡顿,用户体验变差。因此,使用异步操作在后台线程(通过dispatch_async和全局队列dispatch_get_global_queue)执行数据下载任务,主线程可以继续处理其他UI相关的事件。
  2. 并行处理辅助计算任务:辅助计算任务可以并行执行,因为它们之间可能没有先后依赖关系。通过dispatch_groupdispatch_group_async将这些任务提交到全局并发队列,能够充分利用多核处理器的优势,提高整体的执行效率。dispatch_group_notify则用于在所有并行任务完成后执行指定的操作。
  3. UI更新在主线程:在iOS开发中,UIKit的操作必须在主线程进行,否则会出现未定义行为。因此,在数据下载和辅助计算任务完成后,使用dispatch_group_notify回到主线程更新UI,确保UI操作的安全性和稳定性。