iOS开发之-Grand Central Dispatch

来源:互联网 发布:冰箱品牌 知乎 编辑:程序博客网 时间:2024/04/16 16:51



http://blog.csdn.net/nerohoop/article/details/7074780

Grand Central Dispatch


[plain] view plaincopyprint?
  1. dispatch_queue_t dispatch_queue_create (const char * label, dispatch_queue_attr_t attr);  
  2.    
这个函数返回一个objective-C对象引用(C语言中的一个结构体变量指针),并且是带引用计数的。不过该函数可以用于C/C++。
第一个参数是指定所创建队列的一个标签;第二个参数是指明该队列的属性,但是目前为止,Apple并没有去实现它,因此只要并且必须传NULL或nil。

[plain] view plaincopyprint?
  1. void dispatch_async ( dispatch_queue_t queue, dispatch_block_t block);  
将block注册到queue中


[plain] view plaincopyprint?
  1. typedef void (^dispatch_block_t) (void);  


我们可以清楚地看到,这个类型其实是void(^)(void)类型。这意味着你的任务Block没有返回值,也没有任何参数,这样你要在你所定义的任务内对想要的数据进行操作的话基本上只能通过两种方法——
1、对全局数据进行操作;
2、通过注册自己的环境数据,然后在任务中获得进行操作。(稍后讲解)
还有一种方法是通过__block,可以使Block对main()函数中的局部变量进行操作


下面详细谈谈串行分派队列:
1、串行队列的特征:
对于一个串行分派队列,它是按照FIFO(先入先出)的顺序依次执行注册在其内部的任务。其中每个任务都运行在自己独立的线程中。你可以创建多个串行分派队列,而各个串行分派队列之间,执行是可并行的。
比如队列A注册了task1和task2;队列B注册了task3和task4。对于队列A,肯定是执行完task1后再执行task2;同样对于队列B,肯定是执行完task3后再执行task4。但是task1可以与task3或task4并行执行;而同样task2也能与task3或task4并行执行。


2、注册并执行任务:
而将一个任务注册到指定队列并执行一般使用dispatch_async接口。该接口的特点是调用完以后刚被注册的任务并不一定马上被调度。另外还有一个接口是dispatch_sync。但是这个接口几乎很少使用。因为没什么特殊理由需要同步,否则并行就失去意义了。dispatch_sync是将当前注册的任务执行完之后再返回。
而且,当你将task1注册到队列A之后,如果task1中有调用dispatch_sync将task2注册到队列A,那将是非法的;但可以将task3注册到队列B。也就是说,对于在一个队列中正在运行的任务不能将另一个任务注册到自己所被注册的同一个队列。
当然,3楼的代码如果换成dispatch_sync就不需要全局标志了,呵呵。下面贴出来大家可以试试:


然后再介绍一下在Mac OS X中关于Process、Thread以及Task这三个概念:
1、线程(Thread):用于引用执行代码的一个独立的路径。Mac OS X中线程的底层实现基于POSIX线程API。
2、进程(Process):用于引用一个正在运行的可执行程序,它拥有多个线程。
3、任务(Task):用于引用需要被执行的工作的抽象概念。
也就是说一个任务就是一个要被执行的一个例程;而线程的职责就是去执行所指定的任务;进程则是整个应用程序。


semaphore(信号量)机制


[plain] view plaincopyprint?
  1. #import <Foundation/Foundation.h>  
  2. static int myArray[100];  
  3. static void Init(void)  
  4. {  
  5.     int sum = 1;  
  6.     for(int i = 0; i < 100; i++, sum++)  
  7.         myArray[i] = sum + 1;  
  8. }  
  9. int main(int argc, const char * argv[])  
  10. {      
  11.     NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];  
  12.       
  13.     // insert code here...  
  14.     Init();  
  15.       
  16.     // Create a semaphore with zero  
  17.     __block dispatch_semaphore_t sem = dispatch_semaphore_create(0);  
  18.       
  19.     dispatch_queue_t queue = dispatch_queue_create("zenny_chen_firstQueue", nil);  
  20.     dispatch_async(queue, ^(void) {  
  21.         int sum = 0;  
  22.         for(int i = 0; i < 100; i++)  
  23.             sum += myArray[i];  
  24.         NSLog(@"The sum is: %d", sum);  
  25.           
  26.         // signal the semaphore  
  27.         dispatch_semaphore_signal(sem);  
  28.     });  
  29.       
  30.     // wait for the semaphore  
  31.     dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);  
  32.       
  33.     dispatch_release(queue);  
  34.     [pool drain];  
  35.       
  36.     return 0;  
  37. }  

上面三处注释介绍了如何创建、发布、等待一个信号。信号量的基本原理就是生产-消费模式。我们可以理解为吃自助餐,比如巴西烤肉自助餐,呵呵。当你坐在烤炉旁等待烤肉出炉时你没有肉,当然就只能等待,当烤肉的把一片牛肉烤好时,放在你的盘子后你就得到一块烤肉,你可以大快朵颐了。厨师将烤好的肉放在你的盘子里就相当于对你发出一个信号(Signal you with the meat)。因此,每次调用dispatch_semaphore_wait,你盘子里的肉的数量减1,表示你吃了一块肉了;而每次调用dispatch_semaphore_signal,厨师就把烤好的肉放在你的盘子里,你盘子里的肉就加1。一开始创建的时候,盘子里的肉为0。

当主线程在等待信号量时,操作系统会直接将它挂起,因此不会去死做标志轮询,而能够及时将CPU资源给其它可被调度的线程使用。
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 苹果6s国行不能用移动4g怎么办 苹果手机32g内存不够用怎么办 华为荣耀6x忘记了密码怎么办 百度粉色衣服被洗变色了怎么办 粉色衣服放进洗衣机洗变色了怎么办 红米note5a应用锁忘了怎么办 索尼手机死机了怎么办不可拆卸电池 华为手机一直停留在开机画面怎么办 5s用11.4太卡了怎么办 华为荣耀5a手机声音小怎么办 牙签卡在手机插卡针里怎么办 捡的华为手机账号激活不了怎么办 华为平板激活手机密码忘了怎么办 捡个华为手机非要激活才能用怎么办 华为手机没激活想重新激活怎么办 华为手机激活总显示系统繁忙怎么办 华为荣耀7i进水了不开机怎么办 华为荣耀手机进水了怎么办开不开机 华为畅享5s变砖怎么办 我的苹果7机身内存满了怎么办 小米5x拆机后屏幕翘边怎么办 苹果手机设备禁止游戏登入怎么办 苹果7plus玩游戏掉频怎么办 孕期牙套子掉了基牙烂掉了怎么办 美团绑定的信用卡过期了怎么办 苹果6s手机开不开机怎么办 换了散热硅胶后还是死机怎么办 华为畅享6s掉啦怎么办 透明塑料壳被太阳晒的发黄怎么办 新买的手机壳有味道怎么办 刚买的手机壳有异味怎么办 bjd 光油把妆蹭掉了一点怎么办 软皮套手机壳如果大了怎么办 苹果手机自带相机拍照会晃屏怎么办 苹果x手机壳拆不下来怎么办 苹果手机5c屏幕没有反应怎么办 玩穿越火线屏幕两边是黑的怎么办? 8g内存只有2g可用怎么办? 三星7e微信分身打不开怎么办? 光猫的网口1不亮怎么办 两年前的发票发现名头有错误怎么办