浅谈GCD
1.什么是GCD
GCD
Grand Central Dispatch (GCD)是Apple开发的一个多核编程的较新的解决方法。它主要用于优化应用程序以支持多核处理器以及其他对称多处理系统。它是一个在线程池模式的基础上执行的并行任务。在Mac OS X 10.6雪豹中首次推出,也可在IOS 4及以上版本使用。
优点:
·易用:比NSThread更加易用。基于block导致它简单的在不同的代码域进行传递。
·效率:GCD实现功能 轻量、优雅,使得它在很多地方比之专门创建消耗资源的线程更 实用且快速
·性能:GCD自动根据系统负载来增减线程数量,这就减少了上下文切换以及增加了计 算效率
·安全:无需加锁或其他同步机制
2.GCD的使用
创建队列
/***********************创建队列***********************/
//1.串行队列:
dispatch_queue_t que1 = dispatch_queue_create("serial", DISPATCH_QUEUE_SERIAL);
//2.并发队列创建
dispatch_queue_t que2 = dispatch_queue_create("concurrent", DISPATCH_QUEUE_CONCURRENT);
//3.主队列(串行)
dispatch_queue_t mainQqueue = dispatch_get_main_queue();
//4.全局队列(并发)
//第一个0 是优先级,可以自行设置,第二个还没有开发使用,暂时填0
dispatch_queue_t backgroundQueue = dispatch_get_global_queue(0, 0);
添加队列
/***********************添加队列到任务***********************/
//dispatch_async 提交一个异步执行的 block块到队列里面并且直接返回,不用等待block 被调用
//提交一个异步执行的block块,不用等待调用
dispatch_async(que1, ^{
NSLog(@"呵呵");
});
//dispatch_sync 提交一个同步的block到队列中等待,直到block执行完成。在主线程里添加主队列容易造成死锁
//例如: 相当于 ---->NSLog(@"hehe");------>dispatch_sync
dispatch_sync(mainQqueue, ^{
NSLog(@"hehe");
});
//死锁的原因是NSLog(@"hehe")任务等待dispatch_sync执行完,dispatch_sync又需要执行完NSLog(@"hehe")任务这个任务,因为主队列是串行的,造成了阻塞。
队列的一些用法
/***********************队列的用法***********************/
//dispatch_once实现单例模式
[UIApplication sharedApplication];//app的对象
[NSNotificationCenter defaultCenter];//通知中心对象
[UIDevice currentDevice];//当前的设备
[NSUserDefaults standardUserDefaults]; //数据储存
//dispatch_group创建一个分组,监听队列中的任务。
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t groupQueue = dispatch_get_global_queue(0, 0);
//注意:这里是没有先后顺序的
dispatch_group_async(group, groupQueue, ^{
NSLog(@"1-天地不仁");
});
dispatch_group_async(group, groupQueue, ^{
NSLog(@"2-以万物为刍狗");
});
dispatch_group_async(group, groupQueue, ^{
NSLog(@"3-圣人不仁");
});
dispatch_group_async(group, groupQueue, ^{
NSLog(@"4-以百姓为刍狗");
});
//结束之后会发送一个通知,有顺序
dispatch_group_notify(group, groupQueue, ^{
NSLog(@"道德经-老子");
});
//在未来设置一个时间点
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 5);
/*
DISPATCH_TIME_NOW 现在的时间点
NSEC_PER_SEC 秒
time 在未来五秒后
*/
//意思就是在未来的某一时刻(5s后)group会检查任务的执行程度。
long result = dispatch_group_wait(group, time);
/*PS:
* Returns zero on success (all blocks associated with the group completed
* within the specified timeout) or non-zero on error (i.e. timed out).
大意就是返回0就是成功了,不是0就是错误的。
*/
if (result == 0) {
NSLog(@"任务执行成功");
}else{
NSLog(@"任务执行失败");
}
快速高效的遍历。
注意观察输出一万次的时间
//apply迭代
NSMutableArray *array = [NSMutableArray arrayWithCapacity:10000];
for (int i = 0; i<10000; i++) {
[array addObject:[NSNumber numberWithInt:i]];
}
//dispatch_apply能过实现一个高性能的循环迭代
//dispatch_apply 会阻塞当前线程,所以放在后台线程中
/*
size_t iterations:迭代次数
queue:迭代的队列
^(size_t) {
code
}:迭代过程汇总每次要做的事情
^(size_t i):迭代的变量,记得要自己添加。
*/
//使用迭代进行输出,效率是在主线程中的好几倍。
dispatch_async(dispatch_get_global_queue(0, 0), ^{
dispatch_apply(array.count, dispatch_get_global_queue(0, 0), ^(size_t i) {
NSLog(@"%d",[array[i] intValue]);
});
});
精确定时器的运用:
//runLoop使一个线程处于运行状态,不会被销毁。
//最后在runLoop的基础上介绍一下精确的定时器。
_index = 0;
_count = 0;
//屏幕刷新率是60HZ
//即1/60秒调用一次
CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(timeAction)];
[link addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
//CADisplayLink 不受其他线程的影响
long long j =0;
for (long i =0; i<1000000000; i++) {
j+=i;
}
}
- (void)timeAction{
_count ++;
if (_count == 60) {
NSLog(@"_index = %d",_index);
_index ++;
_count = 0;
}
}