iOS开发之-Grand Central Dispatch



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

Grand Central Dispatch


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

  1. void dispatch_async ( dispatch_queue_t queue, dispatch_block_t block);  
将block注册到queue中


  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(信号量)机制


  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资源给其它可被调度的线程使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值