You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多方法并行控制:如何确保method3仅在method1与method2均完成后执行一次

嘿,这个场景我熟!你的现有代码虽然能实现需求,但有两个小瑕疵:一是method3会被两次调用(哪怕只有一次真正执行核心逻辑),二是如果method1和method2在多线程环境下运行,isMethod1Complete、isMethod2Complete这两个变量可能存在线程安全问题。

下面给你几个更优雅的优化方案,按推荐程度排序:

方案1:用GCD Dispatch Group(最推荐,简洁高效)

这是iOS/macOS里处理多任务同步最常用的方式,不需要手动维护状态标记,系统会自动帮我们监听两个任务的完成状态,确保method3只执行一次。

步骤如下:

  1. 先定义一个dispatch_group_t属性,用来管理任务组:
@property (nonatomic, strong) dispatch_group_t taskGroup;
  1. 在合适的地方(比如初始化方法里)创建任务组:
self.taskGroup = dispatch_group_create();
  1. 修改method1和method2,把耗时任务加入任务组:
- (void)method1 {
    // 标记任务进入组
    dispatch_group_enter(self.taskGroup);
    // 把耗时任务放到后台队列执行(如果你的任务已经是异步的,直接在任务结束处调用leave即可)
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // 这里写你的耗时任务逻辑
        
        // 任务完成后标记离开组
        dispatch_group_leave(self.taskGroup);
    });
}

- (void)method2 {
    dispatch_group_enter(self.taskGroup);
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // 这里写你的耗时任务逻辑
        
        dispatch_group_leave(self.taskGroup);
    });
}
  1. 设置任务组的通知,当两个任务都完成时自动调用method3:
// 这里可以指定method3执行的队列,比如主队列(如果需要更新UI)
dispatch_group_notify(self.taskGroup, dispatch_get_main_queue(), ^{
    [self method3];
});

这样method3只会被调用一次,完全不用关心method1和method2谁先完成。

方案2:改进现有逻辑,加线程安全保护+避免重复调用

如果不想用GCD Group,也可以给你的现有逻辑打补丁,解决线程安全和重复调用的问题:

  1. 新增一个标记变量和锁:
@property (nonatomic, assign) BOOL isMethod1Complete;
@property (nonatomic, assign) BOOL isMethod2Complete;
@property (nonatomic, assign) BOOL isMethod3Executed; // 标记method3是否已经执行过
@property (nonatomic, strong) NSRecursiveLock *taskLock; // 用来保证线程安全
  1. 初始化锁:
self.taskLock = [[NSRecursiveLock alloc] init];
  1. 修改method1、method2和拆分method3:
- (void)method1 {
    // 执行耗时任务
    
    [self.taskLock lock];
    self.isMethod1Complete = YES;
    [self.taskLock unlock];
    
    [self checkAndRunMethod3];
}

- (void)method2 {
    // 执行耗时任务
    
    [self.taskLock lock];
    self.isMethod2Complete = YES;
    [self.taskLock unlock];
    
    [self checkAndRunMethod3];
}

// 单独做检查逻辑,避免重复调用
- (void)checkAndRunMethod3 {
    [self.taskLock lock];
    BOOL shouldExecute = self.isMethod1Complete && self.isMethod2Complete && !self.isMethod3Executed;
    if (shouldExecute) {
        self.isMethod3Executed = YES;
    }
    [self.taskLock unlock];
    
    if (shouldExecute) {
        [self realMethod3];
    }
}

- (void)realMethod3 {
    // 这里写原来method3里需要仅执行一次的任务
}

这个方案通过锁解决了多线程下的状态竞争问题,同时用isMethod3Executed确保核心逻辑只执行一次,不会像原来那样method3被调用两次。

方案3:用NSOperation依赖关系

如果你的项目已经在用NSOperation管理任务,那可以通过依赖关系来实现需求:

// 创建操作队列
NSOperationQueue *taskQueue = [[NSOperationQueue alloc] init];

// 封装method1的耗时任务
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
    // 这里写method1里的耗时任务逻辑
}];

// 封装method2的耗时任务
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
    // 这里写method2里的耗时任务逻辑
}];

// 封装method3的任务
NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
    [self method3];
}];

// 设置依赖:op3必须等op1和op2都完成才能执行
[op3 addDependency:op1];
[op3 addDependency:op2];

// 添加所有操作到队列
[taskQueue addOperations:@[op1, op2, op3] waitUntilFinished:NO];

这个方案的优势是任务依赖关系清晰,适合复杂任务调度的场景。

总的来说,GCD Dispatch Group是最省心的方案,代码简洁,不需要维护额外的状态变量,还自带线程安全保障。

内容的提问来源于stack exchange,提问作者arsenium

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:44:08