Grand Central Dispatch可以简化多线程编程。可以将应用程序需要执行的工作拆分为可分散在多个线程和多个cpu上更小的块。多线程还是得了解底层的实现,GCD只是进行了封装。
以下为实例:
#import <UIKit/UIKit.h> @interface ViewController : UIViewController - (IBAction)doWork:(id)sender; @property (weak, nonatomic) IBOutlet UITextView *resultsTextView; @property (weak, nonatomic) IBOutlet UIButton *startButton; @property (weak, nonatomic) IBOutlet UIActivityIndicatorView *spinner; @end
// // ViewController.m // Study20130220 // // Created by Dwen on 13-2-20. // Copyright (c) 2013年 Dwen. All rights reserved. // #import "ViewController.h" @interface ViewController () @end @implementation ViewController @synthesize startButton,resultsTextView,spinner; - (void)viewDidLoad { [super viewDidLoad]; NSLog(@"load view..."); // //定义程序块 // void(^loggerBlock)(void); // //实现程序块 // loggerBlock = ^{NSLog(@"i am test block.");}; // //执行程序块 // loggerBlock(); } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (NSString *)fetchSomethingFromServer{ [NSThread sleepForTimeInterval:1]; return @"Hi there"; } - (NSString *)processData:(NSString *)data{ [NSThread sleepForTimeInterval:2]; return [data uppercaseString]; } - (NSString *)calculateFirstResult:(NSString *)data{ [NSThread sleepForTimeInterval:3]; return [NSString stringWithFormat:@"Number of chars: %d",[data length]]; } - (NSString *)calculateSecondResult:(NSString *)data{ [NSThread sleepForTimeInterval:4]; return [data stringByReplacingOccurrencesOfString:@"E" withString:@"e"]; } - (IBAction)doWork:(id)sender { //并发程序块 startButton.enabled = NO; startButton.alpha = 0.5; [spinner startAnimating]; NSDate *startTime = [NSDate date]; dispatch_async(dispatch_get_global_queue(0, 0), ^{ NSString *fetchedData = [self fetchSomethingFromServer]; NSString *processData = [self processData:fetchedData]; __block NSString *firstResult; __block NSString *secondResult; dispatch_group_t group = dispatch_group_create(); dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{ NSLog(@"calculateFirstResult..."); firstResult = [self calculateFirstResult:processData]; }); dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{ NSLog(@"calculateSecondResult..."); secondResult = [self calculateSecondResult:processData]; }); //dispatch_group_notify指定一个额外的程序块,该程序块将在组中的所有程序块运行完成时执行 dispatch_group_notify(group, dispatch_get_global_queue(0, 0), ^{ NSString *resultsSummary = [NSString stringWithFormat:@"First: [%@]\nSecond: [%@]",firstResult,secondResult]; NSLog(@"resultsSummary :%@",resultsSummary); //dispatch_get_main_queue主线程 dispatch_async(dispatch_get_main_queue(), ^{ NSLog(@"change value."); startButton.enabled = YES; startButton.alpha = 1.0; [spinner stopAnimating]; resultsTextView.text = resultsSummary; }); NSDate *endTime = [NSDate date]; NSLog(@"Completed in %f seconds",[endTime timeIntervalSinceDate:startTime]); }); }); //异步执行 // startButton.enabled = NO; // startButton.alpha = 0.5; // [spinner startAnimating]; // NSDate *startTime = [NSDate date]; // dispatch_async(dispatch_get_global_queue(0, 0), ^{ // NSString *fetchedData = [self fetchSomethingFromServer]; // NSString *processData = [self processData:fetchedData]; // NSString *firstResult = [self calculateFirstResult:processData]; // NSString *secondResult = [self calculateSecondResult:processData]; // NSString *resultsSummary = [NSString stringWithFormat:@"First: [%@]\nSecond: [%@]",firstResult,secondResult]; // NSLog(@"resultsSummary :%@",resultsSummary); // dispatch_async(dispatch_get_main_queue(), ^{ // NSLog(@"change value."); // startButton.enabled = YES; // startButton.alpha = 1.0; // [spinner stopAnimating]; // resultsTextView.text = resultsSummary; // }); // NSDate *endTime = [NSDate date]; // NSLog(@"Completed in %f seconds",[endTime timeIntervalSinceDate:startTime]); // }); //同步执行 // NSDate *startTime = [NSDate date]; // NSString *fetchedData = [self fetchSomethingFromServer]; // NSString *processData = [self processData:fetchedData]; // NSString *firstResult = [self calculateFirstResult:processData]; // NSString *secondResult = [self calculateSecondResult:processData]; // NSString *resultsSummary = [NSString stringWithFormat:@"First: [%@]\nSecond: [%@]",firstResult,secondResult]; // resultsTextView.text = resultsSummary; // NSDate *endTime = [NSDate date]; // NSLog(@"Completed in %f seconds",[endTime timeIntervalSinceDate:startTime]); } @end
异步执行需花10秒,而并发程序块只花了7秒,大大提高了效率。在真实的应用程序中,加速程度将取决于所执行的工作和可用的资源。只有在多个cpu核心可用时,执行cpu资源密集型的计算才能受益于此技术。
=================================================================================
NSThread和GCD是多线程的两种实现方式,NSThread实现起来比GCD稍微复杂些,GCD要比较简单些,GCD是C语言提供的API。GCD支持多核CPU处理。
在GCD中,有3种类型的派发队列:
1、串行队列。串行队列通常用于同步访问一个特定的资源,每次只能执行一个任务。使用函数dispatch_queue_create,可以创建串行队列。
2、并发队列。也叫全局派发队列,可以并发地执行一个或多个任务。并发队列分为高、中、低3个优先级队列,中级为默认级别。可以使用调用dispatch_get_global_queue函数设定优先级来访问队列。
3、主队列。它在应用程序的主线程中,用于更新UI。使用dispatch_get_main_queue函数,可以获得主队列。
以下两种图片下载方式,效率完全不一样。
同步下载图片:
NSString *picPath = [NSString stringWithFormat:@"%@?imageView2/0/w/%d",_mdExhibitVo.exhibitPic,(int)(([UIScreen mainScreen].bounds.size.width-8*2)*2)]; picPath = [picPath stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; NSData * picData = [NSData dataWithContentsOfURL:[NSURL URLWithString:picPath]]; self.imageView.image = [UIImage imageWithData:picData]];
异步下载图片:
NSString *smallImgStr = [NSString stringWithFormat:@"%@?imageView/0/w/200/q/20",_mdExhibitWorkVo.worksPic]; smallImgStr = [smallImgStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; dispatch_queue_t downloadQueue = dispatch_queue_create("com.test.works.image", NULL); dispatch_async(downloadQueue, ^{ NSData *imgData = [NSData dataWithContentsOfURL:[NSURL URLWithString:smallImgStr]]; UIImage *img = [UIImage imageWithData:imgData]; dispatch_async(dispatch_get_main_queue(), ^{ _headerImageView.image = img; [[ImageProgressView sharedASIImageViewAppearance] setPlaceholderImage:img]; }); });