iOS多线程开发:GCD

Grand Central Dispatch (GCD)是Apple开发的一个多核编程的较新的解决方法。它主要用于优化应用程序以支持多核处理器以及其他对称多处理系统。它是一个在线程池模式的基础上执行的并行任务。在Mac OS X 10.6雪豹中首次推出,也可在IOS 4及以上版本使用(源自于百度知道)。GCD时基于C语言的,在使用的时候完全由系统来管理线程,不需要开发人员编写线程代码,只要定义所需要执行的任务,然后在添加到适当的调度队列(dispatch queue)当中,GCD会帮助你创建线程并调度你的任务,线程的管理直接交由系统控制,无需开发者操作。

GCD的dispatch queue严格遵循先进先出(FIFO)的原则,开发人员添加到dispatch queue的工作单元始终按照加入的顺序穿行或者并发地执行任务。

dispatch queue通常用法:

(1)通过dispatch_get_main_queue获取主队列Main queue,我们通常会在主线程中来刷新UI,比如,异步加载图片,然后在主线程中将图片填充到UI上:

// 开启异步线程下载图片
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        
        NSURL * url = [NSURL URLWithString:@"http://img2.3lian.com/img2007/10/28/123.jpg"];
        UIImage * image = [UIImage imageWithData:[NSData dataWithContentsOfURL:url]];
        
        // 获得主线程
        dispatch_queue_t queue = dispatch_get_main_queue();
        // 在主线程中将 image 填充到 UI 中,即刷新UI
        dispatch_async(queue, ^{
            
            self.imageView.image = image;
        });
    });


(2) dispatch_sync 和 dispatch_sync_f 函数可同步的将任务添加到队列中,这两个方法会阻塞当前线程,直到任务结束,代码演示:

/ 创建串行队列
    dispatch_queue_t queue = dispatch_queue_create("com.example.MyQueue", NULL);
    
    // 开启同步任务,会阻塞该线程
    dispatch_sync(queue, ^{
       
        NSLog(@"开启一个同步任务");
    });

(3)在多个任务同时进行的时候,我们可以使用dispatch_group_async函数将多个任务关联到一个Dispatch Group和相应的队列中,group会并发执行这些任务。同时,可以用Dispatch Group来阻塞一个线程,直到group关联的所有任务都完成后,再执行后续任务。具体使用可见如下方法:

// 根据 urlString 获取 image
- (UIImage *)downloadImageWithURLString:(NSString *)urlString {
    
    NSURL * url = [NSURL URLWithString:urlString];
    UIImage * image = [UIImage imageWithData:[NSData dataWithContentsOfURL:url]];
    return image;
}

- (void)downloadImages {
    
    // 创建组
    dispatch_group_t group = dispatch_group_create();
    
    __block UIImage * imageOne;
    __block UIImage * imageTwo;
    __block UIImage * imageThree;
    
    // 关联第一个任务到组group
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        
        NSString * urlOne = @"http://a2.att.hudong.com/38/59/300001054794129041591416974.jpg";
        imageOne = [self downloadImageWithURLString:urlOne];
    });
    
    // 关联第二个任务
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        
        NSString * urlTwo = @"http://www.gdsoftga.com/uploads/allimg/120516/2-120516152643a5.jpg";
        imageTwo = [self downloadImageWithURLString:urlTwo];
    });
    
    // 关联第三个任务
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        
        NSString * urlThree = @"http://pic.nipic.com/2007-11-08/200711819133664_2.jpg";
        imageThree = [self downloadImageWithURLString:urlThree];
    });
    
    // 等待组中的任务执行完毕,会发送通知,执行此处代码,回到主线程中执行block
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        
        // TODO:此处将下载下来图片填充到UI中,刷新UI
        
    });
}

注意:不要在同步任务中再开启同步任务,这样会导致死锁;即使实在并发队列中,也要尽量避免这样做,不然会导致线程不安全。





你可能感兴趣的:(iOS开发)