iOS开发-多线程多任务的依赖的解决方案

2,040 阅读4分钟

在多线程开发中往往会遇到多个任务并发,但是还有任务之间具有依赖关系,比如下图:

任务依赖图

使用NSOperationQueue要比GCD方便一些,代码更简洁。

1. 使用NSOperationQueue设置依赖

- (void)testOperation {
    NSLog(@"开始----%@",[NSThread currentThread]);
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    NSBlockOperation *opA = [NSBlockOperation blockOperationWithBlock:^{
        
        sleep(3);
        NSLog(@"完成任务A----%@",[NSThread currentThread]);
    }];
    
    NSBlockOperation *opB = [NSBlockOperation blockOperationWithBlock:^{
        
        sleep(2);
        NSLog(@"完成任务B---%@",[NSThread currentThread]);
    }];
    
    NSBlockOperation *opC = [NSBlockOperation blockOperationWithBlock:^{
       
        sleep(1);
         NSLog(@"完成任务C---%@",[NSThread currentThread]);
    }];
    
    NSBlockOperation *opD = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"完成任务D---%@",[NSThread currentThread]);
    }];
    
    NSBlockOperation *opE = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"完成任务E---%@",[NSThread currentThread]);
    }];
    
    [opD addDependency:opA];
    [opD addDependency:opB];
    
    [opE addDependency:opB];
    [opE addDependency:opC];
    
    
    [queue addOperation:opA];
    [queue addOperation:opB];
    [queue addOperation:opC];
    [queue addOperation:opD];
    [queue addOperation:opE];
}

运行结果:

2019-07-15 17:07:57.918930+0800 xxtest[62847:2808690] 开始----<NSThread: 0x600002dbe900>{number = 1, name = main}
2019-07-15 17:07:58.922080+0800 xxtest[62847:2808777] 完成任务C----<NSThread: 0x600002dc3780>{number = 3, name = (null)}
2019-07-15 17:07:59.924180+0800 xxtest[62847:2808780] 完成任务B----<NSThread: 0x600002dc37c0>{number = 4, name = (null)}
2019-07-15 17:07:59.924480+0800 xxtest[62847:2808792] 完成任务E----<NSThread: 0x600002dc59c0>{number = 5, name = (null)}
2019-07-15 17:08:00.921409+0800 xxtest[62847:2808779] 完成任务A----<NSThread: 0x600002dc5900>{number = 6, name = (null)}
2019-07-15 17:08:00.921659+0800 xxtest[62847:2808778] 完成任务D----<NSThread: 0x600002d35500>{number = 7, name = (null)}

2. 使用 @synchronized+dispatch_semaphore

//@property(nonatomic,strong) NSObject *mySyn;
//@property(nonatomic,strong) NSLock *lockD;
//@property(nonatomic,strong) NSLock *lockE;

-(void)synTest{
    
     NSLog(@"开始----%@",[NSThread currentThread]);
    dispatch_queue_t queue =  dispatch_queue_create("com.xxx.customQueue", DISPATCH_QUEUE_CONCURRENT);
    self.mySyn = [[NSObject alloc]init];
    self.D_count = 0;
    self.E_count = 0;
    
    dispatch_semaphore_t D_sema = dispatch_semaphore_create(0);
    dispatch_semaphore_t E_sema = dispatch_semaphore_create(0);
    
    dispatch_async(queue, ^{
        
        sleep(3);
        NSLog(@"完成任务A----%@",[NSThread currentThread]);
        @synchronized (self.mySyn) {
            self.D_count = self.D_count + 1;
            if (self.D_count==2) {
                dispatch_semaphore_signal(D_sema);
            }
        }
        
    });
    
    dispatch_async(queue, ^{
        
        sleep(2);
         NSLog(@"完成任务B----%@",[NSThread currentThread]);
        
        @synchronized (self.mySyn) {
            self.D_count = self.D_count + 1;
            if (self.D_count==2) {
                dispatch_semaphore_signal(D_sema);
            }
            
            self.E_count = self.E_count + 1;
            if (self.E_count==2) {
                dispatch_semaphore_signal(E_sema);
            }
        }
       
        
    });
    
    dispatch_async(queue, ^{
        
        sleep(1);
         NSLog(@"完成任务C----%@",[NSThread currentThread]);
        
        @synchronized (self.mySyn) {
            self.E_count = self.E_count + 1;
            if (self.E_count==2) {
                dispatch_semaphore_signal(E_sema);
            }
        }
        
        
    });
    
    dispatch_async(queue, ^{
        dispatch_semaphore_wait(D_sema, DISPATCH_TIME_FOREVER);
         NSLog(@"完成任务D----%@",[NSThread currentThread]);
        dispatch_semaphore_signal(D_sema);
    });
    
    dispatch_async(queue, ^{
        dispatch_semaphore_wait(E_sema, DISPATCH_TIME_FOREVER);
         NSLog(@"完成任务E----%@",[NSThread currentThread]);
        dispatch_semaphore_signal(E_sema);
        
    });
    
  
    
}

执行结果:

2019-07-15 17:11:18.540308+0800 xxtest[62873:2811422] 开始----<NSThread: 0x60000118f600>{number = 1, name = main}
2019-07-15 17:11:19.544241+0800 xxtest[62873:2811459] 完成任务C----<NSThread: 0x6000011081c0>{number = 3, name = (null)}
2019-07-15 17:11:20.544484+0800 xxtest[62873:2811456] 完成任务B----<NSThread: 0x6000011dc180>{number = 4, name = (null)}
2019-07-15 17:11:20.544678+0800 xxtest[62873:2811529] 完成任务E----<NSThread: 0x6000011f4d80>{number = 5, name = (null)}
2019-07-15 17:11:21.545102+0800 xxtest[62873:2811457] 完成任务A----<NSThread: 0x60000110b040>{number = 6, name = (null)}
2019-07-15 17:11:21.545316+0800 xxtest[62873:2811458] 完成任务D----<NSThread: 0x6000011fb180>{number = 7, name = (null)}

3. 使用 dispatch_group+dispatch_semaphore


-(void)groupAndSema{
    
    NSLog(@"开始----%@",[NSThread currentThread]);
    
    dispatch_queue_t queue =  dispatch_queue_create("com.xxx.customQueue", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_semaphore_t B_sema = dispatch_semaphore_create(0);
    
    dispatch_group_t groupAB =dispatch_group_create();
    
    dispatch_group_async(groupAB,queue, ^{
        sleep(3);
        NSLog(@"完成任务A----%@",[NSThread currentThread]);
    });
    
    dispatch_group_async(groupAB,queue, ^{
        sleep(2);
        NSLog(@"完成任务B----%@",[NSThread currentThread]);
          dispatch_semaphore_signal(B_sema);
    });
    
    dispatch_group_t groupBC =dispatch_group_create();
    dispatch_group_async(groupBC,queue, ^{
        dispatch_semaphore_wait(B_sema, DISPATCH_TIME_FOREVER);
    });
    
    dispatch_group_async(groupBC,queue, ^{
        sleep(1);
        NSLog(@"完成任务C----%@",[NSThread currentThread]);
    });
    
    
    dispatch_group_notify(groupAB,queue, ^{
       NSLog(@"完成任务D----%@",[NSThread currentThread]);
    });
    
    dispatch_group_notify(groupBC,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
        NSLog(@"完成任务E----%@",[NSThread currentThread]);
    });
}

2019-07-16 11:07:23.328392+0800 xxtest[5590:141062] 开始----<NSThread: 0x600000fba880>{number = 1, name = main}
2019-07-16 11:07:24.328872+0800 xxtest[5590:141167] 完成任务C----<NSThread: 0x600000f3c680>{number = 3, name = (null)}
2019-07-16 11:07:25.329991+0800 xxtest[5590:141154] 完成任务B----<NSThread: 0x600000fdd240>{number = 4, name = (null)}
2019-07-16 11:07:25.330212+0800 xxtest[5590:141166] 完成任务E----<NSThread: 0x600000f3c6c0>{number = 5, name = (null)}
2019-07-16 11:07:26.328750+0800 xxtest[5590:141156] 完成任务A----<NSThread: 0x600000fcad40>{number = 6, name = (null)}
2019-07-16 11:07:26.328931+0800 xxtest[5590:141156] 完成任务D----<NSThread: 0x600000fcad40>{number = 6, name = (null)}