GCD(Grand Central Dispatch)教程

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


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值