GCD入门介绍四---- dispatch_group_async和dispatch_barrier_async

我们在开发的过程中,可能碰到如下的情况:异步下载两张图片,然后合并成一张图片。此时就需要使用dispatch group,例子1如下面代码所示:

dispatch_group_t group = dispatch_group_create();
    dispatch_queue_t queue = dispatch_queue_create("com.jwl.www", DISPATCH_QUEUE_CONCURRENT);
    dispatch_group_async(group, queue, ^{
            NSLog(@"jwl 1111");
    });
    
    dispatch_group_async(group, queue, ^{
        NSLog(@"jwl 2222");
    });
    
    dispatch_group_async(group, queue, ^{
        NSLog(@"jwl 3333");
    });
    
    dispatch_group_notify(group, queue, ^{
        NSLog(@"jwl finish");
    });
控制台输出结果:

2016-01-27 22:37:14.050 dispatch_group[1633:27456] jwl 2222
2016-01-27 22:37:14.050 dispatch_group[1633:27452] jwl 1111
2016-01-27 22:37:14.050 dispatch_group[1633:27466] jwl 3333
2016-01-27 22:37:14.050 dispatch_group[1633:27466] jwl finish
前面三个线程并行执行,所以执行顺序不定。执行顺序会发生变化,但是jwl finish一定是最后输出!
例子2:异步下载两张图片,然后合并成一张图片

//
//  ViewController.m
//  dispatch_group
//
//  Created by bcc_cae on 16/1/27.
//  Copyright © 2016年 bcc_cae. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()
@property (nonatomic,strong) UIImage *firstImage;
@property (nonatomic,strong) UIImage *secondImage;
@property (nonatomic,weak) UILabel *textLabel;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    [self composeImage];
}

- (void)composeImage
{
    UILabel *textLabel = [[UILabel alloc] initWithFrame:CGRectMake(200, 200, 0, 0)];
    textLabel.text = @"正在下载图片";
    [textLabel sizeToFit];
    [self.view addSubview:textLabel];
    self.textLabel = textLabel;
    [self group];
 }

- (void)group
{
    UIImageView *imageView = [[UIImageView alloc] init];
    [self.view addSubview:imageView];
    
    dispatch_group_t group = dispatch_group_create();
    dispatch_queue_t queue = dispatch_queue_create("cn.jwl.www", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_group_async(group, queue, ^{
        NSLog(@"正在下载第一张图片");
        NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"https://img-blog.csdn.net/20160114203205409?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center"]];
        
        NSLog(@"第一张图片下载完毕");
        self.firstImage = [UIImage imageWithData:data];
        
    });
    
    dispatch_group_async(group, queue, ^{
        NSLog(@"正在下载第二张图片");
        NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"https://img-blog.csdn.net/20160114203205409?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center"]];
        
        NSLog(@"第二张图片下载完毕");
        self.secondImage = [UIImage imageWithData:data];
        
    });
    
    dispatch_group_notify(group, queue, ^{
        UIGraphicsBeginImageContext(CGSizeMake(300, 400));
        [self.firstImage drawInRect:CGRectMake(0, 0, 150, 400)];
        [self.secondImage drawInRect:CGRectMake(150, 0, 150, 400)];
        
        UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        
        dispatch_async(dispatch_get_main_queue(), ^{
            UIImageView *imageView = [[UIImageView alloc] initWithImage:newImage];
            [self.view addSubview:imageView];
            self.textLabel.text = @"图片合并完毕";
        });
    });
}

@end
2. dispatch_barrier_async

在并行队列中,为了保持某些任务的顺序,需要等待一些任务完成后才能继续进行,使用 barrier 来等待之前任务完成,避免数据竞争等问题。 dispatch_barrier_async 函数会等待追加到Concurrent Dispatch Queue并行队列中的操作全部执行完之后,然后再执行 dispatch_barrier_async 函数追加的处理,等 dispatch_barrier_async 追加的处理执行结束之后,Concurrent Dispatch Queue才恢复之前的动作继续执行。
打个比方:比如你们公司周末跟团旅游,高速休息站上,司机说:大家都去上厕所,速战速决,上完厕所就上高速。超大的公共厕所,大家同时去,程序猿很快就结束了,但程序媛就可能会慢一些,即使你第一个回来,司机也不会出发,司机要等待所有人都回来后,才能出发。 dispatch_barrier_async 函数追加的内容就如同 “上完厕所就上高速”这个动作。


参考资料:

《招聘一个靠谱的iOS》面试题参考答案(下)

iOS开发:深入理解GCD 第二篇(dispatch_group、dispatch_barrier、基于线程安全的多读单写)

你可能感兴趣的:(ios,app开发,多线程)