多线程 依赖

来源:互联网 发布:nginx 全局变量赋值 编辑:程序博客网 时间:2024/05/22 00:43

如何实现一个任务依赖于其他2个任务的实现方法?


1、使用dispatch_group实现

  1. 创建dispatch_group_t

  2. 添加任务(block)

  3. 添加结束任务(如清理操作、通知UI等)

//1.创建队列组dispatch_group_t group = dispatch_group_create();//2.创建队列dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);//3.多次使用队列组的方法执行任务, 只有异步方法//3.1.执行3次循环dispatch_group_async(group, queue, ^{    for (NSInteger i = 0; i < 3; i++) {        NSLog(@"group-01 - %@", [NSThread currentThread]);    }});//3.2.主队列执行8次循环dispatch_group_async(group, dispatch_get_main_queue(), ^{    for (NSInteger i = 0; i < 8; i++) {        NSLog(@"group-02 - %@", [NSThread currentThread]);    }});//3.3.执行5次循环dispatch_group_async(group, queue, ^{    for (NSInteger i = 0; i < 5; i++) {        NSLog(@"group-03 - %@", [NSThread currentThread]);    }});//4.都完成后会自动通知dispatch_group_notify(group, dispatch_get_main_queue(), ^{    NSLog(@"完成 - %@", [NSThread currentThread]);});

或者:

dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

2、使用dispatch_barrier_async实现

dispatch_barrier_async的作用就是向某个队列插入一个block,当队列前面的任务完成后,再执行barrier的这个block。执行完barrier这个block后,才能执行队列后面的block。

所以实现方法是:把被依赖的任务放在barrier之前。

self.synchronizationQueue = dispatch_queue_create([queueName cStringUsingEncoding:NSASCIIStringEncoding], DISPATCH_QUEUE_CONCURRENT);
dispatch_sync(self.synchronizationQueue, ^{
        result = self.currentMemoryUsage;
});
dispatch_sync(self.synchronizationQueue, ^{
        AFCachedImage *cachedImage = self.cachedImages[identifier];
        image = [cachedImage accessImage];
});
dispatch_barrier_sync(self.synchronizationQueue, ^{
        AFCachedImage *cachedImage = self.cachedImages[identifier];
        if (cachedImage != nil) {
            [self.cachedImages removeObjectForKey:identifier];
            self.currentMemoryUsage -= cachedImage.totalBytes;
            removed = YES;
        }
});



3、使用NSOperation的addDependency实现

1)、一个operation依赖多个operation

当某个NSOperation对象依赖于其它NSOperation对象的完成时,就可以通过addDependency方法添加一个或者多个依赖的对象,只有所有依赖的对象都已经完成操作,当前NSOperation对象才会开始执行操作。另外,通过removeDependency方法来删除依赖对象。

[java] view plain copy
  1. [operation2 addDependency:operation1];  
依赖关系不局限于相同queue中的NSOperation对象,NSOperation对象会管理自己的依赖, 因此完全可以在不同的queue之间的NSOperation对象创建依赖关系


唯一的限制是不能创建环形依赖,比如A依赖B,B依赖A,这是错误的


示例如下:

//操作依赖
//处理图片的耗时操作在子线程中执行
NSBlockOperation *blockOp = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"blockOp 下载图片 thread = %@",[NSThread currentThread]);
}];
NSBlockOperation *blockOp1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"blockOp1 给图片添加水印 thread = %@",[NSThread currentThread]);
}];
NSBlockOperation *blockOp2 = [NSBlockOperation blockOperationWithBlock:^{
[NSThread sleepForTimeInterval:2.0];
NSLog(@"blockOp2 保存图片 thread = %@",[NSThread currentThread]);
}];
//给blockOp1添加依赖关系,使blockOp1在blcokOp执行结束后执行
[blockOp1 addDependency:blockOp];//也就是下载结束之后再给图片添加水印,然后保存图片。一种依赖关系
[blockOp2 addDependency:blockOp1];
//创建队列(把上面要干的事情丢到队列中同时执行--有点类似GCD中的异步,并发,开启了多个线程)
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
//添加到队列
[queue addOperation:blockOp];
[queue addOperation:blockOp1];
[queue addOperation:blockOp2];


2)、一个operation依赖一个operation

另外,除了以上这种,让一个operation依赖于多个operation。

还可以让operation封装多个操作,这样一个operation仅仅依赖另一个即可:


NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
        //......
}];

[operation2 addExecutionBlock:^{
//....
}];

[operation2 addExecutionBlock:^{
//....
}];

以上operation2封装了3个操作,然后:

[blockOp2 addDependency:operation2];即可


0 0
原创粉丝点击