GCD (Grand Central Dispatch) 

 

  GCD: 将应用程序需要执行的工作拆分为可分散在多个线程和多个CPU 上更小的块

demo 效果图:

1—— .h 文件

   
   
   
   
  1.  #import <UIKit/UIKit.h> 
  2. @interface ViewController : UIViewController 
  3. - (IBAction)doWork:(id)sender; 
  4. @property (retain, nonatomic) IBOutlet UIButton *StartBtn; 
  5. @property (retain, nonatomic) IBOutlet UITextView *resultTextView; 
  6. @property (retain, nonatomic) IBOutlet UIActivityIndicatorView *spinner; 
  7.  
  8. @end 

 2— .m 文件

 

   
   
   
   
  1. #import "ViewController.h" 
  2.  
  3. @implementation ViewController 
  4. @synthesize StartBtn; 
  5. @synthesize resultTextView; 
  6. @synthesize spinner; 
  7.  
  8.  
  9. - (NSString *)fetchSomethingFromServer 
  10.     //将应用程序锁定  1 秒  
  11.     [NSThread sleepForTimeInterval:1]; 
  12.     return @"hi there"; 
  13.  
  14. - (NSString *)processData:(NSString *)data 
  15.     [NSThread sleepForTimeInterval:2]; 
  16.     return [data uppercaseString]; 
  17.  
  18. - (NSString *)calculateFirstResult:(NSString *)data 
  19.     [NSThread sleepForTimeInterval:3]; 
  20.     return [NSString stringWithFormat:@"number of chars :%d",[data length]]; 
  21.      
  22.  
  23. - (NSString *)calculateSecondResult:(NSString *)data 
  24.     [NSThread sleepForTimeInterval:4]; 
  25.     return [data stringByReplacingOccurrencesOfString:@"E" withString:@"e"]; 
  26.  
  27.  
  28.  
  29. - (IBAction)doWork:(id)sender{ 
  30.      
  31.     StartBtn.enabled = NO
  32.     StartBtn.alpha = 0.5; 
  33.     [spinner startAnimating]; 
  34.      
  35.     NSDate *startTime = [NSDate date]; 
  36.     // dispatch_get_global_queue(dispatch_queue_priority_t priority, unsigned long flags) 
  37.     // dispatch_get_global_queue() 抓取一个已经存在并且始终可用的全局队列 该函数接收俩个参数:
  38. //  1_用于指定优先级(传入0表示使用默认的优先级) ,2_目前未使用并且始终为0() 
  39.      
  40.     dispatch_async(dispatch_get_global_queue(0, 0), ^{ 
  41.         NSString *fetchedData = [self fetchSomethingFromServer]; 
  42.         NSString *processedData = [self processData:fetchedData]; 
  43. //        NSString *firstResult = [self calculateFirstResult:processedData]; 
  44. //        NSString *secondResult = [self calculateSecondResult:processedData]; 
  45.        
  46.         //calculateFirstResult && calculateSecondResult 不需要顺序执行 ,并发的执行他们可以更显著的提高速度。 
  47.         // GCD 提供一种途径来完成此任务,使用所谓的“分派组”,将一个组上 的 上下文中通过 dispatch_group_async() 函数异步分派的所有程序块设置为松散的,以尽可能快的执行,如果可能,将它们分发给多个线程来执行。 
  48.         // 也可以使用dispathch_group_notify() 指定一个 额外的程序块,该程序块将在组中的所有程序块即将运行完成时执行。 
  49.         __block NSString *firstResult; 
  50.         __block NSString *secondResult; 
  51.         dispatch_group_t group = dispatch_group_create(); 
  52.         dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{ 
  53.             firstResult = [[self calculateFirstResult:processedData]retain]; 
  54.         }); 
  55.          
  56.         dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{ 
  57.             secondResult = [[self calculateSecondResult:processedData]retain]; 
  58.         }); 
  59.          
  60.         // 使用dispathch_group_notify() 指定一个 额外的程序块,该程序块将在组中的所有程序块即将运行完成时执行。 
  61.        dispatch_group_notify(group, dispatch_get_global_queue(0, 0), ^{ 
  62.                NSString *resultsSummary = [NSString stringWithFormat:@"first :[%@] \n second: [%@] \n",firstResult,secondResult]; 
  63.                //        resultTextView.text = resultsSummary
  64.                 
  65.                //在后台线程联系任何GUI对象是不可能的,必须将工作传回到主线程!可再次调用dispatch_async 这次传入dispatch_get_main_queue() 函数返回的队列,该函数总是 提供存在于主线程上的特殊队列,并准备执行需要使用主线程的程序块 
  66.                dispatch_async(dispatch_get_main_queue(), ^{ 
  67.                    // 回到主线程才可以出发按钮事件 
  68.                    StartBtn.enabled = YES
  69.                    StartBtn.alpha = 1.0; 
  70.                    [spinner stopAnimating]; 
  71.                     
  72.                    resultTextView.text = resultsSummary
  73.                }); 
  74.                NSDate *endTime = [NSDate date]; 
  75.                NSLog(@"complete in %f seconds",[endTime timeIntervalSinceDate:startTime]); 
  76.             
  77.            // 在最后一个程序块中释放 它们, 
  78.            [firstResult release]; 
  79.            [secondResult release]; 
  80.              
  81.             }); 
  82.         }) ; 
  83.         
  84.  
  85. #pragma mark - View lifecycle 
  86.  
  87. - (void)viewDidLoad 
  88.     [super viewDidLoad]; 
  89.     // Do any additional setup after loading the view, typically from a nib. 
  90.  
  91. - (void)viewDidUnload 
  92.     [self setStartBtn:nil]; 
  93.     [self setResultTextView:nil]; 
  94.     [self setSpinner:nil]; 
  95.     [super viewDidUnload]; 
  96.     // Release any retained subviews of the main view. 
  97.     // e.g. self.myOutlet = nil
  98.  
  99.  
  100. - (void)dealloc { 
  101.     [StartBtn release]; 
  102.     [resultTextView release]; 
  103.     [spinner release]; 
  104.     [super dealloc]; 
  105. @end