GCD 整理(二)

来源:互联网 发布:无主之地ol激活码淘宝 编辑:程序博客网 时间:2024/06/06 12:40

Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法。

GCD的用法

dispatch_async

//  后台执行: dispatch_async(dispatch_get_global_queue(0, 0), ^{      // something });
<pre name="code" class="objc" style="line-height: 18px; font-family: Verdana, 'Lucida Grande', Arial, Helvetica, sans-serif;">// 主线程执行: dispatch_async(dispatch_get_main_queue(), ^{      // something });

dispatch_async开启一个异步操作,第一个参数是指定一个gcd队列,第二个参数是分配一个处理事物的程序块到该队列。

dispatch_get_global_queue(0, 0),指用了全局队列。

一般来说系统本身会有3个队列。

global_queue,current_queue,以及main_queue.

获取一个全局队列是接受两个参数,第一个是我分配的事物处理程序块队列优先级。分高低和默认,0为默认2为高,-2为低。

#define DISPATCH_QUEUE_PRIORITY_HIGH     2 #define DISPATCH_QUEUE_PRIORITY_DEFAULT  0 #define DISPATCH_QUEUE_PRIORITY_LOW     (-2)  


dispatch_once

 // 一次性执行: static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{     // code to be executed once });

全局只执行一次,一般用作单例的实现。下面是单例的例子

<pre name="code" class="objc">// 单例+(NewHttp *)share{    static NewHttp *_sharDL = nil;    static dispatch_once_t onceDLMgr = 0;    dispatch_once(&onceDLMgr, ^{        _sharDL = [[NewHttp alloc] init];    });    return _sharDL;}

dispatch_after

 // 延迟2秒执行: 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 });

dispatch_after只是延时提交block,并不是延时后立即执行。所以想用dispatch_after精确控制运行状态的朋友可要注意了~

用dispatch_after的时候就会用到dispatch_time_t变量,但是如何创建合适的时间呢?答案就是用dispatch_time函数,其原型如下:

dispatch_time_t dispatch_time ( dispatch_time_t when, int64_t delta );

第一个参数一般是DISPATCH_TIME_NOW,表示从现在开始。

那么第二个参数就是真正的延时的具体时间。

这里要特别注意的是,delta参数是“纳秒!”,就是说,延时1秒的话,delta应该是“1000000000”=。=,太长了,所以理所当然系统提供了常量,如下:

#define NSEC_PER_SEC 1000000000ull  //每秒有多少纳秒。#define USEC_PER_SEC 1000000ull    //每秒有多少毫秒#define NSEC_PER_USEC 1000ull      //每毫秒有多少纳秒。

dispatch_queue_create

 // 自定义dispatch_queue_t dispatch_queue_t urls_queue = dispatch_queue_create("<span style="color: rgb(37, 37, 37); line-height: 28px;"><span style="font-size:12px;">com.example.MyQueue</span></span>", NULL); dispatch_async(urls_queue, ^{     // your code  }); dispatch_release(urls_queue);

dispatch_queue_create,创建队列用的,它的参数只有两个,原型如下:

dispatch_queue_t dispatch_queue_create ( const char *label, dispatch_queue_attr_t attr );
在网上的大部分教程里(甚至Apple自己的文档里),第二个参数传的是“NULL”。 但是dispatch_queue_attr_t类型是有已经定义好的常量的,所以我认为,为了更加的清晰、严谨,最好如下创建队列

//串行队列dispatch_queue_t queue = dispatch_queue_create("com.example.MyQueue", DISPATCH_QUEUE_SERIAL);//并行队列dispatch_queue_t queue = dispatch_queue_create("com.example.MyQueue", DISPATCH_QUEUE_CONCURRENT);

常量就是为了使代码更加“易懂”,更加清晰,既然有,为啥不用呢~


dispatch_suspend

dispatch_suspend != 立即停止队列的运行

dispatch_suspend,dispatch_resume提供了“挂起、恢复”队列的功能,简单来说,就是可以暂停、恢复队列上的任务。但是这里的“挂起”,并不能保证可以立即停止队列上正在运行的block,看如下例子:

dispatch_queue_t queue = dispatch_queue_create("me.tutuge.test.gcd", DISPATCH_QUEUE_SERIAL);//提交第一个block,延时5秒打印。dispatch_async(queue, ^{    [NSThread sleepForTimeInterval:5];    NSLog(@"After 5 seconds...");});//提交第二个block,也是延时5秒打印dispatch_async(queue, ^{    [NSThread sleepForTimeInterval:5];    NSLog(@"After 5 seconds again...");});//延时一秒NSLog(@"sleep 1 second...");[NSThread sleepForTimeInterval:1];//挂起队列                        NSLog(@"suspend...");dispatch_suspend(queue);//延时10秒                NSLog(@"sleep 10 second...");[NSThread sleepForTimeInterval:10];//恢复队列            NSLog(@"resume...");dispatch_resume(queue);

运行结果如下:

2015-04-01 00:32:09.903 GCDTest[47201:1883834] sleep 1 second...2015-04-01 00:32:10.910 GCDTest[47201:1883834] suspend...2015-04-01 00:32:10.910 GCDTest[47201:1883834] sleep 10 second...2015-04-01 00:32:14.908 GCDTest[47201:1883856] After 5 seconds...2015-04-01 00:32:20.911 GCDTest[47201:1883834] resume...2015-04-01 00:32:25.912 GCDTest[47201:1883856] After 5 seconds again...

可知,在dispatch_suspend挂起队列后,第一个block还是在运行,并且正常输出。

结合文档,我们可以得知,dispatch_suspend并不会立即暂停正在运行的block,而是在当前block执行完成后,暂停后续的block执行。

所以下次想暂停正在队列上运行的block时,还是不要用dispatch_suspend了吧~



 // 合并汇总结果 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), ^{      // 汇总结果 });


0 0
原创粉丝点击