GCD(Grand Central Dispatch)教程

来源:互联网 发布:淘宝佣金软件购买 编辑:程序博客网 时间:2024/04/27 05:08

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任务

http://blog.csdn.net/developer_zhang/article/details/8910919

6、GCD任务分组

http://blog.csdn.net/developer_zhang/article/details/8916518

7、构建自己的分派队列

http://blog.csdn.net/developer_zhang/article/details/8916582

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 Objectvoid (^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 Objectvoid (^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 Objectvoid 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


0 0
原创粉丝点击