GCD是纯C语言,但又溶有面向对象思想、基于Block。
1、GCD优点:
2、GCD的使用
2.1.dispatch async异步操作
2.1.1.定义想要执行的操作(任务),追加到适当的队列中(Dispatch Queue)
2.12.Queue类型:
(1)Serial Dispatch Queue — 等待现在正在执行的任务处理结束(串行)
(2)Concurrent Dispatch Queue — 不等待现在正在执行的任务处理结束(并行、并发)
2.1.3.自己定义queue,把任务加到自定义的queue之中
(1)创建queue
//第一个参数:给队列起名字
//第二个参数:queue的类型 (默认是串行的)
dispatch_queue_t queue1 = dispatch_queue_create("com.wxhl.gcd.Queue1", NULL);
dispatch_queue_t queue2 = dispatch_queue_create("com.wxhl.gcd.Queue2", DISPATCH_QUEUE_CONCURRENT); //并行的queue
(2)创建要执行的任务,加到queue中执行
dispatch_async(queue2, ^{
for (int i = 0; i < 50; i ++) {
NSLog(@"GCD : %d", i);
}
});
2.1.4.使用系统给提供的queue(推荐)
两种
Main Dispatch Queue Global Dispatch Queue
串行(主线程) 并行
//main
dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_async(mainQueue, ^{
;
});
//global
//参数一:优先级
//参数二:标识符
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(globalQueue, ^{
//请求网络数据
//显示在UI界面上
dispatch_async(dispatch_get_main_queue(), ^{
//UI相关的代码
});
});
//主线程
for (int i = 0; i < 50; i ++) {
NSLog(@"主线程 : %d", i);
}
//async: asynchronous 将任务异步的追加到队列中
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"async");
});
2.2 dispatch sync同步操作
//sync: synchronous 将任务同步的追加到队列中(等队列中的任务执行完,再将任务追加到队列)
//是同步追加,不是任务同步执行,在串行队列中,任务才同步执行
dispatch_sync(dispatch_get_global_queue(0, 0), ^{
NSLog(@"sync");
});
**dispatch_sync的问题:容易产生死锁**
示例1:
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"hello");
});
NSLog(@"主线程");
//上述代码在主队列中执行指定的block,等待其执行结束
//而主队列中本来就在执行上述代码,无法执行追加的block
示例2:
//串行的队列
dispatch_queue_t queue = dispatch_queue_create("com.wxhl.GCD.queue", NULL);
dispatch_async(queue, ^{
dispatch_sync(queue, ^{
NSLog(@"串行队列");
});
});
3. GCD高级用法
3.1 Dispatch After
一段时间之后,把要执行的任务追加到队列当中
- (void)viewDidLoad {
[super viewDidLoad];
//创建时间
//相对的时间点 相对第一个参数多长时间之后
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 3ull * NSEC_PER_SEC);
//时间的单位
//NSEC_PER_SEC 秒
//NSEC_PER_MSEC 毫秒
//NSEC_PER_USEC 微秒
//dispatch_time_t 指定的时间
dispatch_after(time, dispatch_get_main_queue(), ^{
NSLog(@"after 3s");
});
//第二种用法
dispatch_after_f(dispatch_time(DISPATCH_TIME_NOW, 3ull * NSEC_PER_SEC), dispatch_get_main_queue(), NULL, func1);
//自己使用
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5ull * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
;
});
#warning 注意
//1.不是一段时间之后执行相应的任务 (而是把要执行的任务追加到队列当中)
//2.主线程 runloop 1/60秒检测事件, 追加的时间范围 3s - (3 + 1/60)s
}
void func1()
{
}
@end
3.2 Dispatch Group
dispatch_group_async :使用 group 监视 队列任务的执行
dispatch_group_notify:所有任务执行结束汇总,不阻塞当前线程
dispatch_group_wait: 等待直到所有任务执行结束,中途不能取消,阻塞当前线程
- (void)viewDidLoad {
[super viewDidLoad];
//1.创建 group
dispatch_group_t group = dispatch_group_create();
//2.获取队列
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
//3.使用 group 监视 队列任务的执行
dispatch_group_async(group, queue, ^{
NSLog(@"task 1");
});
dispatch_group_async(group, queue, ^{
NSLog(@"task 2");
});
dispatch_group_async(group, queue, ^{
NSLog(@"task 3");
});
dispatch_group_async(group, queue, ^{
sleep(6);
NSLog(@"task 4");
});
//(1)监视的函数
//监视到队列里任务执行结束,执行block里面的任务
dispatch_group_notify(group, queue, ^{
//结束处理
NSLog(@"done");
});
//(2)
//等待time时间,根据wait函数的返回值确定队列中任务是否执行结束,5秒后汇总结果,不管任务有没有执行完
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC);
//dispatch_group_wait 指定的时间之后 看一眼queue的任务是否执行完毕
//如果执行完,返回0
//如果没有执行完,返回非0值
long result = dispatch_group_wait(group, time);
if (result == 0) {
NSLog(@"finish");
} else {
NSLog(@"not finish");
}
//dispatch_group_wait 会堵塞当前线程 一直在调用这个函数 等待指定的时间之后才会返回
sleep(2);
NSLog(@"main");
}
@end
3.3 dispatch once实现单例
ViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
//dispatch once
//保证block里的任务只执行一次
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSLog(@"只会执行一次");
});
}
@end
AddressBook.m
#import "AddressBook.h"
static AddressBook *instance = nil;
@implementation AddressBook
/*
* 单例 单例模式 尽量不要使用
* 1.含义:一个类只创建一个对象
* 2.生命周期:从创建开始,应用程序退出结束
* 3.取得单例对象的方法,命名规则: share default
* 4.内存管理尽量由该类来管理
*/
+ (AddressBook *)sharedInstance
{
//onceToken 标记block里的代码是否执行过
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[AddressBook alloc] init];
});
return instance;
}
//alloc 会自动调用 allocWithZone:
//zone 空间 分配内存空间(zone),创建对象
+ (id)allocWithZone:(NSZone *)zone
{
if (instance == nil) {
instance = [super allocWithZone:zone];
}
return instance;
}
@end
4. 小结:
多线程之GCD(Grand Central Dispatch)
原文地址:http://blog.csdn.net/mainning/article/details/44923191