iOS多线程并发时如何控制任务执行顺序

2018-04-22  本文已影响426人  不丶是你的益达

在日常的开发中我们主要用GCD和NSOperation去管理多线程开发,串行队列无论是在异步还是同步的线程中都会按照既定的顺序去执行,而在并行队列任务的执行顺序就是不是很好控制了。在某些特定的情况下需要并行队列按照某种特定的顺序执行避免数据竞争。针对GCD和NSOperation有不同的方法。

在NSOperation可以很方便的通过添加依赖,使任务按照特定的顺序执行。oper2 addDependency oper1 此时任务2在任务1执行之后才会去执行

//任务1
    NSBlockOperation *oper1 =[NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"oper1");
        [NSThread sleepForTimeInterval:1.0];
    }];
    
    //任务2
    NSBlockOperation *oper2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"oper2");
    }];
    
    //任务3
    NSBlockOperation *oper3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"oper3");
        [NSThread sleepForTimeInterval:1];
    }];
    
    //添加依赖
    [oper3 addDependency:oper1];
    [oper2 addDependency:oper3];
    
    //创建队列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    [queue addOperations:@[oper1, oper2, oper3] waitUntilFinished:NO];

运行结果

oper1
oper3
oper2

在添加依赖的情况下运行结果是不确定的,因为是并发的。当然也可以通过removeDependency来移除依赖。 另外在NSOperation非主队列中默认是并行的,想要实现串行可以给NSOperationQueue设置最大并发数为1达到这个效果(setMaxConcurrentOperationCount)再就是添加依赖。

在GCD中苹果提供了栅栏函数dispatch_get_current_queue来实现在并行队列中的有序执行。dispatch_get_current_queue的作用就是在并行队列中等待之前的任务完成后再执行栅栏函数中的任务,最后再去执行后面的任务。

dispatch_queue_t queue = dispatch_queue_create("wq", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_async(queue, ^{
        NSLog(@"thread1");
        [NSThread sleepForTimeInterval:1.0];
    });
    
    dispatch_barrier_async(queue, ^{
        NSLog(@"thread2");
    });
    
    dispatch_async(queue, ^{
        NSLog(@"thread3");
    });

运行结果
thread1 thread2 thread3
注意栅栏函数必须和自定义的并行队列一起使用,和全局并行队列一起使用是没有任何效果的,等同于dispatch_async。而dispatch_barrier_syncdispatch_barrier_async作用差不多,只是dispatch_barrier_sync会阻塞当前线程。

上一篇下一篇

猜你喜欢

热点阅读