GCD简介

来源:互联网 发布:网络会员密码开锁 编辑:程序博客网 时间:2024/06/06 05:00

一、关于GCD

  GCD为Grand Central Dispatch的缩写,是苹果开发的一种操作机制,在Mac OS X 10.6中首次推出,并引入到了iOS4.0。

  GCD是一套低层API,不是Cocoa框架的一部分,从基本功能上讲,GCD有点像NSOperationQueue,他们都可以将单一任务提交至工作队列来并发地或者串行地执行。GCD比之NSOpertionQueue更底层更高效,开发者只需要定义想执行的任务并追加到适当的Dispatch Queue中,GCD就能生成必要的线程并计划执行任务。

  GCD的主要部件是一个FIFO队列和一个线程池,前者用来添加任务,后者用来执行任务。GCD中的FIFO队列称为dispatch queue,它可以保证先进来的任务先得到执行(但不保证一定先执行结束)。

  GCD的API很大程度上基于block,当然,GCD也可以脱离block来使用,比如使用传统c机制提供函数指针和上下文指针,实践证明,当配合block使用时,GCD非常简单易用且能发挥其最大能力。

 

二、GCD的使用

dispatch queue主要有以下几种:

1)运行在主线程的 Main queue

dispatch_async(dispatch_get_main_queue(), ^{      

// something 

});

 

2)并行队列 global queue

  一般用于后台执行,并行队列的执行顺序与其加入队列的顺序相同(FIFO)。

dispatch_async(dispatch_get_global_queue(0, 0),^{     

 //something 

}); 

 

通常,我们可以在global_queue中做一些long-running的任务,完成后在main_queue中更新UI,以避免UI阻塞:

dispatch_async(dispatch_get_global_queue(0, 0), ^{  

    // long-running task  

    dispatch_async(dispatch_get_main_queue(), ^{  

        // update UI  

    });  

});  

  上面提到dispatch_async这个接口,用来提交blcok给指定queue进行异步执行。这个接口会在成功提交block后立即返回,然后继续执行下去。

  与之相对应的是dispatch_sync接口,提交block以供同步执行,这个接口会等到block执行结束才返回。

 

3)串行队列 serial queues

  一般用于按顺序同步访问,串行队列在同一个时间只执行一个任务。

dispatch_queue_t urls_queue =dispatch_queue_create("blog.tang.com", NULL); 

dispatch_async(urls_queue, ^{      

// your code 

 });

 dispatch_release(urls_queue);

 

4)只被执行一次的 dispatch_once

它可以保证整个应用程序生命周期中某段代码只被执行一次!

static dispatch_once_t  onceToken;  

dispatch_once(&onceToken, ^{  

    // code to be executed once  

}); 

 

5)延迟执行 dispatch_after

double delayInSeconds = 2.0; 

dispatch_time_t  popTime = dispatch_time(DISPATCH_TIME_NOW,delayInSeconds * NSEC_PER_SEC); 

dispatch_after(popTime, dispatch_get_main_queue(),^(void){  

   // code to be executed on the main queue after delay

 });  

 

6)合并汇总结果 dispatch_group

可能经常会有这样一种情况:我们现在有2个Block要执行,我们不在乎它们执行的顺序,我们只希望在这2个Block执行完之后再执行某个操作。这个时候就需要使用dispatch_group了:

 dispatch_group_t  group = dispatch_group_create();

 dispatch_group_async(group,dispatch_get_global_queue(0,0), ^{ 

// 并行执行的线程一 

}); 

dispatch_group_async(group,dispatch_get_global_queue(0,0), ^{      

// 并行执行的线程二 

}); 

dispatch_group_notify(group,dispatch_get_global_queue(0,0), ^{     

 // 汇总结果或者说同步地等待一段时间看是否结束:

 });

 

7)设置优先级 dispatch_set_target_queue

  通过dispatch_set_target_queue函数可以设置一个dispatch queue的优先级,或者指定一个dispatch source相应的事件处理提交到哪个queue上。

dispatch_set_target_queue(serialQ, globalQ); 

 

8)重复执行 dispatch_apply

dispatch_apply(10, globalQ, ^(size_t index) {  

    // do sth. 10 times  

}); 

 

9)同步地等待一段时间看是否结束 dispatch_group_wait

dispatch_time_t  time = dispatch_time(DISPATCH_TIME_NOW, 1ull * NSEC_PER_SEC);  

dispatch_group_wait(group, time); 

需要注意的是,dispatch_group_wait实际上会使当前的线程处于等待的状态,也就是说如果是在主线程执行dispatch_group_wait,在上面的Block执行完之前,主线程会处于卡死的状态。

 

10)栅栏 dispatch_barrier_async

  通过dispatch_barrier_async函数提交的任务会等它前面的任务执行结束才开始,然后它后面的任务必须等它执行完毕才能开始。

dispatch_async(concurrentQ, blk0);  

dispatch_async(concurrentQ, blk1);  

dispatch_barrier_async(concurrentQ, blk_barrier);  

dispatch_async(concurrentQ, blk2);  

dispatch_barrier_async就如同它的名字一样,在队列执行的任务中增加“栅栏”,在增加“栅栏”之前已经开始执行的block将会继续执行,当dispatch_barrier_async开始执行的时候其他的block处于等待状态,dispatch_barrier_async的任务执行完后,其后的block才会执行。

 

11)线程队列的挂起与执行

// 挂起队列

dispatch_suspend(queue);

// 恢复队列执行

dispatch_resume(queue);

这里需要特别说明一下:GCD原生并不支持取消操作。dispatch_suspend函数也只能暂停开启新的未执行的block,已经处于执行中的block是无法暂停的。



参考博文:

1、http://justsee.iteye.com/blog/1883409

2、http://www.cnblogs.com/pure/archive/2013/03/31/2977420.html

3、http://blog.csdn.net/jasonblog/article/details/7816999

 

0 0