1、GCD(Grand Central Dispatch)教程
http://www.dreamingwish.com/dream-2012/gcdgrand-central-dispatch-jiao-cheng.html
2、利用GCD延迟执行任务的方法
// 延迟2秒执行:
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
// code to be executed on the main queue after delay
});
3、创建自己的Queue
dispatch_queue_t custom_queue = dispatch_queue_create(“customQueue”, NULL);
dispatch_async(custom_queue, ^{
//doing something in custom_queue
});
dispatch_release(custom_queue);
4、利用GCD并行多个线程并且等待所有线程结束之后再执行其它任务
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(0,0), ^{
// 并行执行的线程一
});
dispatch_group_async(group, dispatch_get_global_queue(0,0), ^{
// 并行执行的线程二
});
dispatch_group_notify(group, dispatch_get_global_queue(0,0), ^{
// 汇总结果
});
5、GCD上异步执行非UI任务
6、GCD任务分组
7、构建自己的分派队列
7、GCD执行延迟操作
/*
推迟三秒执行printString方法
withObject:传的参数
*/
[self performSelector:@selector(printString:) withObject:@"Grand Central Dispatch" afterDelay:3.0];
//设置时间为2
double delayInSeconds = 2.0;
//创建一个调度时间,相对于默认时钟或修改现有的调度时间。
dispatch_time_t delayInNanoSeconds =dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
//推迟两纳秒执行
dispatch_queue_t concurrentQueue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_after(delayInNanoSeconds, concurrentQueue, ^(void){
NSLog(@"Grand Center Dispatch!");
});
//设置时间
double delayInSeconds = 2.0;
dispatch_time_t delayInNanoSeconds =
dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//调用C函数processSomething
dispatch_after_f(delayInNanoSeconds, concurrentQueue,
NULL,
processSomething);
8、GCD任务最多只执行一次
//一个用于调度一次函数的标识
static dispatch_once_t onceToken;
//Block Object
void (^executedOnlyOnce)(void) = ^{
static NSUInteger numberOfEntries = 0;
numberOfEntries++;
NSLog(@"Executed %lu time(s)", (unsigned long)numberOfEntries);
};
//声明一个队列
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//执行一次的队列
dispatch_once(&onceToken, ^{ dispatch_async(concurrentQueue,
executedOnlyOnce);
});
9、使用 dispatch_sync函数在一个分派队列上执行同步任务
/**************Objc Method Start*********/
//Block Object
void (^printFrom1To1000)(void) = ^{
NSUInteger counter = 0;
for (counter = 1;counter <= 1000;counter++){
NSLog(@"Counter = %lu - Thread = %@",
(unsigned long)counter,
[NSThread currentThread]);
}
};
//测试方法
-(void)testMethod{
/*
Dispatch_get_global_queue 函数的第一个参数说明了并发队列的优先级,这个属性 GCD 必须替程序员检
索。优先级越高,将提供更多的 CPU Timeslice 来获取该队列执行的代码。
Dispatch_get_global_queue 函数的第一个参数:
DISPATCH_QUEUE_PRIORITY_LOW
您的任务比正常任务用到更少的 Timeslice。
DISPATCH_QUEUE_PRIORITY_DEFAULT
执行代码的默认系统优先级将应用于您的任务。
DISPATCH_QUEUE_PRIORITY_HIGH
和正常任务相比,更多的 Timeslices 会应用到你的任务中。
Dispatch_get_global_queue 函数的第二个参数已经保存了,只要一直给它输入数值 0 就可以了。
*/
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_sync(concurrentQueue, printFrom1To1000);
dispatch_sync(concurrentQueue, printFrom1To1000);
}
/**************Objc Method End*********/
/**************C Method Start*********/
//Block Object
void print2From1To1000(void *paramContext){
NSUInteger counter = 0; for (counter = 1;counter <= 1000;counter++){
NSLog(@"Counter = %lu - Thread = %@",
(unsigned long)counter, [NSThread currentThread]);
}
}
//测试方法
-(void)testMethod2{
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_sync_f(concurrentQueue, NULL,print2From1To1000);
dispatch_sync_f(concurrentQueue, NULL,print2From1To1000);
}
/**************C Method End*********/
10、总结
一个 APP 的主线程是处理 UI 事件的线程。如果你在主线程执行一个长时间运行的任务,就要注意 APP的 UI 会没有响应或者响应缓慢。为了避免这一点,你可以创建一个独立线程和/或计时器,它们会分别执行各自的任务(即使是一个长时间运行的任务)同时又不会阻塞主线程。
#import "ZYViewController.h"
@interface ZYViewController ()
@end
@implementation ZYViewController
@synthesize startButton,resultsTextView;
@synthesize spinner;
-(NSString *)fechSomethingFromServer{
//让线程休眠1秒
[NSThread sleepForTimeInterval:1];
return @"Hi there";
}
-(NSString *)processData:(NSString *)data{
[NSThread sleepForTimeInterval:2];
//大写转换
return [data uppercaseString];
}
-(NSString *)caculateFirstResult:(NSString *)data{
[NSThread sleepForTimeInterval:3];
//获得长度
return [NSString stringWithFormat:@"Number of chars:%d",[data length]];
}
-(NSString *)caculateSenondResult:(NSString *)data{
[NSThread sleepForTimeInterval:4];
//将“E”替换成“e”
return [data stringByReplacingOccurrencesOfString:@"E" withString:@"e"];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)dealloc {
[startButton release];
[resultsTextView release];
[spinner release];
[super dealloc];
}
//不使用GCD时此方法执行时间为10s
- (IBAction)doWorking:(id)sender {
startButton.enabled = NO;
startButton.alpha = 0.5;
[spinner startAnimating];
//获得当前时间
NSDate* startTime = [NSDate date];
/**
*dispatch_async:
*我们将代码包装在一个程序块中并将它传递给一个名为dispatch_async的GCD函数。
*第一个参数:一个GCD队列
*第二个参数:为分配给这个队列的程序块
*dispatch_get_global_queue:
*抓取一个已经存在并始终可用的全局队列。
*第一个参数:制定了不同的优先级,比如DISPATCH_QUEUE_PRIORITY_HIGH或者DISPATCH_QUEUE_PRIORITY_LOW,传0相当于传入DISPATCH_QUEUE_PRIORITY_DEFAULT,实际获取一个不同的全局队列,系统将对该队列分配不同的优先级。
*第二个参数 这个值保留以供将来使用。应该总是使用0。
*/
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSString* fetchedData = [self fechSomethingFromServer];
NSString* processedData = [self processData:fetchedData];
//由于这两个变量是动态的所以要用__block修饰
__block NSString* firstResult;
__block NSString* secondResult;
/**
*分派组。将在一个组的上下文中通过dispatch_group_async()函数异步分派的所有程序块设置为松散的,以尽可能快地执行,如果可能,将他们分发给多个线程同时执行。
*/
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
firstResult = [self caculateFirstResult:processedData];
});
dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
secondResult = [self caculateSenondResult:processedData];
});
/**
*也可以使用dispatch_group_notify()指定一个额外的程序块,该程序块将在组中的所有程序块运行完成时执行。
*/
dispatch_group_notify(group, dispatch_get_global_queue(0, 0), ^{
NSString* resultsSummary = [NSString stringWithFormat:@"First:[%@]\nSecond:[%@]",firstResult,secondResult];
/**
*从后台联系到的任何GUI对象是不可能的,所以需要调用另一个分派函数,将工作回到主线程!再次调用传入dispatch_get_main_queue()函数返回的队列,该函数总是提供用于主线程上的特殊队列,并准备执行需要使用主线程的模块。
*/
dispatch_async(dispatch_get_main_queue(), ^{
startButton.enabled = YES;
startButton.alpha = 1;
[spinner stopAnimating];
//为resultsTextView的text属性赋值
resultsTextView.text = resultsSummary;
});
});
NSDate* endTime = [NSDate date];
//获得时间差单位 s
NSLog(@"Completed in %f seconds",[endTime timeIntervalSinceDate:startTime]);
});
}
@end