Barrier的使用

Barrier主要用於在多個異步操作完成之後,統一對非線程安全的對象進行更新, 如NSMutableString/NSMutableArray…

  • Barrier的工作原理

這裏寫圖片描述

將所有之前添加的異步執行完成之後,在同一個線程中,順序執行 block 中的代碼

接下來我們看一下它是如何實現的 ?

  • 首先創建一個併發隊列
_queue = dispatch_queue_create("ejParadise", DISPATCH_QUEUE_CONCURRENT);

注意: 必須是自定義的, 不能使用 _queue = dispatch_get_global_queue(0, 0); 否則執行效果沒有影響

  • 準備工作
- (NSMutableArray *)photoList {
    if (_photoList == nil) {
        _photoList = [NSMutableArray array];
    }

    return _photoList;
}
  • 下載圖片
// 開啓多個任務,分別下載圖片
- (void)loadPictures:(int)index {

    dispatch_async(_queue, ^{
        // 模擬延時
        [NSThread sleepForTimeInterval:1.0];

        // 模擬從網絡下載圖片
        NSString *fileName = [NSString stringWithFormat:@"%02d.jpg", index % 10 + 1];
        NSString *path = [[NSBundle mainBundle] pathForResource:fileName ofType:nil];

        UIImage *image = [UIImage imageWithContentsOfFile:path];

        // 將圖像添加到數組
        // NSMutableArray 不是線程安全的,如果同一個時間點,多個線程項數組添加,有可能會出現崩潰
        // 要解決這個問題,需要一個特殊的函數
        // 將所有之前添加的異步執行完成之後,在同一個線程中,順序執行 block 中的代碼
        dispatch_barrier_async(_queue, ^{
            NSLog(@"添加圖片 %@ %@", fileName, [NSThread currentThread]);

            [self.photoList addObject:image];
        });

//        [self.photoList addObject:image];
        NSLog(@"下載完成 %@ %@", fileName, [NSThread currentThread]);
    });
}
  • 調用下載
for (int i = 0; i < 10; ++i) {
    [self loadPictures:i];
}

這樣就可以確保圖片完成加載後才執行Block裏面的內容添加圖片

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章