关于CGD的一些领悟

GCD相对来说是一种更优雅的方式,看如下代码:

复制代码
NSString* parameter = [self getSomeParameter];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    NSString* result = [self fetchResultFromWebWithParameter:parameter];
    dispatch_async(dispatch_get_main_queue(), ^{
        [self updateUIWithResult:result];
    });
});

复制代码

 

在上面的代码中,出现了一种奇怪的格式:

^{code...}



GCD是和block紧密相连的,所以最好先了解下block。GCD是C level的函数,这意味着它也提供了C的函数指针作为参数。

下面首先来看GCD的使用:

dispatch_async(dispatch_queue_t queue, dispatch_block_t block);

async表明异步运行,除了async,还有sync(同步),delay(延时)

block代表的是你要做的事情,

queue则是你把任务交给谁来处理了.

dispatch_async 这个函数是异步的,这就意味着它会立即返回而不管block是否运行结束。因此,我们可以在block里运行各种耗时的操作(如网络请求) 而同时不会阻塞UI线程。

 

之所以程序中会用到多线程是因为程序往往会需要读取数据,然后更新UI。为了良好的用户体验,读取数据的操作会倾向于在后台运行,这样以避免阻塞主线程。

之所以程序中会用到多线程是因为程序往往会需要读取数据,然后更新UI.为了良好的用户体验,读取数据的操作会倾向于在后台运行,这样以避免阻塞主线程.GCD里就有三种queue来处理.

       先来介绍一下 Main queue:

  顾名思义,运行在主线程,由dispatch_get_main_queue获得.和ui相关的就要使用Main Queue.

[cpp]  view plain copy
  1. //GCD下载图片刷新主界面的例子  
  2. /* 
  3. - (IBAction)touchUpInsideByThreadOne:(id)sender { 
  4.     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
  5.         NSURL * url = [NSURL URLWithString:@"http://avatar.csdn.net/2/C/D/1_totogo2010.jpg"]; 
  6.         NSData * data = [[NSData alloc]initWithContentsOfURL:url]; 
  7.         UIImage *image = [[UIImage alloc]initWithData:data]; 
  8.         if (data != nil) { 
  9.             dispatch_async(dispatch_get_main_queue(), ^{ 
  10.                 self.imageView.image = image; 
  11.             }); 
  12.         } 
  13.     }); 
  14. }*/  

通过与线程池的配合,dispatch queue分为下面两种:而系统默认就有一个串行队列main_queue和并行队列global_queue:

  •      Serial Dispatch Queue -- 线程池只提供一个线程用来执行任务,所以后一个任务必须等到前一个任务执行结束才能开始。
  •      Concurrent Dispatch Queue -- 线程池提供多个线程来执行任务,所以可以按序启动多个任务并发执行。

而系统默认就有一个串行队列main_queue和并行队列global_queue:

[cpp]  view plain copy
  1. dispatch_queue_t globalQ = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);  
  2. dispatch_queue_t mainQ = dispatch_get_main_queue();  
通常,我们可以在global_queue中做一些long-running的任务,完成后在main_queue中更新UI,避免UI阻塞,无法响应用户操作:
[cpp]  view plain copy
  1. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{  
  2.         // long-running task  
  3.         dispatch_async(dispatch_get_main_queue(), ^{  
  4.             // update UI  
  5.         });  
  6.     });  

FIFO(First Input First Output),即先进先出队列。在超市购物之后会提着我们满满的购物车来到收银台排在结账队伍的最后,眼睁睁地看着前面的客户一个个离开。这就是一种先进先出机制,先排队的客户先行结账离开。
 
为了验证Serial queue的FIFO特性,写了如下的验证代码:发现的确是顺序执行的。

[cpp]  view plain copy
  1. - (IBAction)touchUpInsideByThreadOne:(id)sender {  
  2.     NSDate *da = [NSDate date];  
  3.     NSString *daStr = [da description];  
  4.     const char *queueName = [daStr UTF8String];  
  5.     dispatch_queue_t myQueue = dispatch_queue_create(queueName, DISPATCH_QUEUE_SERIAL);  
  6.       
  7.     dispatch_async(myQueue, ^{  
  8.         [NSThread sleepForTimeInterval:6];  
  9.         NSLog(@"[NSThread sleepForTimeInterval:6];");  
  10.     });  
  11.       
  12.     dispatch_async(myQueue, ^{  
  13.         [NSThread sleepForTimeInterval:3];  
  14.         NSLog(@"[NSThread sleepForTimeInterval:3];");  
  15.     });  
  16.       
  17.     dispatch_async(myQueue, ^{  
  18.         [NSThread sleepForTimeInterval:1];  
  19.         NSLog(@"[NSThread sleepForTimeInterval:1];");  
  20.     });  
  21.       
  22.     dispatch_release(myQueue);  
  23. }  
运行结果为:

[cpp]  view plain copy
  1. 2013-07-24 16:37:14.397 NSThreadAndBlockDemo[1924:12303] [NSThread sleepForTimeInterval:6];  
  2. 2013-07-24 16:37:17.399 NSThreadAndBlockDemo[1924:12303] [NSThread sleepForTimeInterval:3];  
  3. 2013-07-24 16:37:18.401 NSThreadAndBlockDemo[1924:12303] [NSThread sleepForTimeInterval:1];  

dispatch_once

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

[cpp]  view plain copy
  1. static dispatch_once_t onceToken;  
  2.     dispatch_once(&onceToken, ^{  
  3.         // code to be executed once  
  4.     });  
 
 
//宏定义
 

#define kBgQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)


- (void)viewDidLoad

{

    [super viewDidLoad];

    dispatch_async(kBgQueue, ^{

        NSData* data = [NSData dataWithContentsOfURLkLatestKivaLoansURL];

        [self performSelectorOnMainThread:@selector(fetchedData:) withObject:datawaitUntilDone:YES];

    });

}


dispatch_async会向kBgQueue队列中添加新的任务去执行,这里kBgQueue队列使用dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)获得。

你可能感兴趣的:(关于CGD的一些领悟)