dispatch_barrier(阻塞)
1 barrier的作用
1.1主要用于在多个异步操作完成之后,统一对非线程安全的对象进行更新。
1.2 适合于大规模的I/O操作。
1.3 当访问数据库或文件的时候,更新数据的时候不能和其它更新或读取的操作在同一时间执行,可以使用 dispatch_barrier_async解决。
2 barrier的演练
模拟从网络上下载很多张图片,并且把下载完成的图片添加到mutableArray中(所有图片下载完一起加到数组中)
//第一步: 定义一个用于保存图片的可变数组
@interface ViewController () {
// 定义一个并发队列
dispatch_queue_t _queue;
}
/// 图片数组
@property (nonatomic, strong) NSMutableArray *photoList;
@end
//第二步: 懒加载
/// 懒加载
- (NSMutableArray *)photoList {
if (_photoList == nil) {
_photoList = [NSMutableArray array];
}
return _photoList;
}
//第三步: 拖入素材,模拟从网络下载图片
- (void)viewDidLoad {
[super viewDidLoad];
_queue = dispatch_queue_create("itheima", DISPATCH_QUEUE_CONCURRENT);
for (int i = 1; i <= 1000; i++) {
[self downloadImage:i];
}
}
// 模拟从网络上下载很多张图片, 并且将下载完成的图片添加到 NSMutableArray 中
- (void)downloadImage: (int)index {
// 异步下载
dispatch_async(_queue, ^{
// 模拟从网络下载图片
NSString *fileName = [NSString stringWithFormat:@"%02d.jpg", index % 10 + 1];
NSString *path = [[NSBundle mainBundle] pathForResource:fileName ofType:nil];
UIImage *image = [UIImage imageWithContentsOfFile:path];
// 将图像添加到数组
dispatch_barrier_async(_queue, ^{
NSLog(@"添加图片 %@ %@", fileName, [NSThread currentThread]);
// 将图像添加到数组
[self.photoList addObject:image];
});
NSLog(@"下载完成 %@ %@", fileName, [NSThread currentThread]);
});
}
//第四步: 打印photoList中的图片数量
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
NSLog(@"图片数量: %tu", self.photoList.count);
}
共同点:
1、等待在它前面插入队列的任务先执行完
2、等待他们自己的任务执行完再执行后面的任务
不同点:
1、dispatch_barrier_sync将自己的任务插入到队列的时候,需要等待自己的任务结束之后才会继续插入被写在它后面的任务,然后执行它们
2、dispatch_barrier_async将自己的任务插入到队列之后,不会等待自己的任务结束,它会继续把后面的任务插入到队列,然后等待自己的任务结束后才执行后面任务。
PS 全局队列和并发队列的区别:
1,全局队列没有名字,但是并发队列有名字。有名字可以便于查看系统日志
2,全局队列是所有应用程序共享的(所以这里的barrier里面的队列必须自己创建 官方API推荐:如果是用全局并发队列久退化成一般的异步函数)
3,在mrc的时候,全局队列不用手动释放,但是并发队列需要。