上一章我们简单介绍了iOS多线程,本章我们讲解GCD多线程
GCD (Grand Central Dispatch) 是 iOS 多任务的核心。在 Mac OS X 10.6 雪豹中首次推出,后被引入到了 iOS 4.0 中。GCD 是基于 C 的 API,是底层的框架,因此效率最高
/*
分组的主要目的 是判断一组操作 是否全部执行结束
原理 将需要执行的操作 添加到同一个分组下 如果其中的某一个操作结束 就会组中移除 当组里面的操作数变为0的 说明所以的操作全部结束
*/
//1.创建一个分组 管理任务
dispatch_group_t myGroup = dispatch_group_create();
//2.获取一个队列 管理的任务放在哪一个线程中来管理
//主队列就表示任务放在主线程中 自定义队列就表示任务放在分线程中(子线程)
//dispatch_queue_t 表示一个队列表示获取一个队列表示获取一个队列全局队列 官方提供一个队列 该队列 默认的是并发处理 线程中的任务可以同时处理多个全局队列 官方提供一个队列 该队列 默认的是并发处理 线程中的任务可以同时处理多个
//dispatch_get_global_queue()
dispatch_queue_t HIGH = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_queue_t DEFAULT = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_queue_t LOW = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);
dispatch_queue_t BACKGROUN = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
//0 系统要求填入一个标志符 必须是0 但是实际这个0 并没有什么用 不填系统不会讲相应的队列返回 直接返回空
//3.通过队列执行一个任务 这个任务是在分组中异步执行
dispatch_group_async(myGroup, BACKGROUN, ^{
for(int i = 0; i < 5; i++){
NSLog(@"DISPATCH_QUEUE_PRIORITY_BACKGROUND");
}
});
dispatch_group_async(myGroup, LOW, ^{
for(int i = 0; i < 5; i++){
NSLog(@"DISPATCH_QUEUE_PRIORITY_LOW");
}
});
dispatch_group_async(myGroup, DEFAULT, ^{
for(int i = 0; i < 5; i++){
NSLog(@"DISPATCH_QUEUE_PRIORITY_DEFAULT");
}
});
dispatch_group_async(myGroup, HIGH, ^{
for(int i = 0; i < 5; i++){
NSLog(@"DISPATCH_QUEUE_PRIORITY_HIGH");
}
});
//dispatch_group_notify()表示一个通知 分组中所有任务执行结束的通知
//dispatch_get_main_queue() 获取主队列
dispatch_group_notify(myGroup, dispatch_get_main_queue(), ^{
NSLog(@"分组中所有任务执行结束");
});
/*
总结:分组中管理的任务并发执行 执行结束的通知方法应该交给主队列来管理 由主线程来执行
注意:在指定优先级之后,同一个队列会按照这个优先级执行,当然这不是串行队列,所以不存在绝对回调先后,打印控制台不一定是按照严格的顺序显示
*/
//1.创建一个队列
dispatch_queue_t myQueue = dispatch_queue_create("MY_QUEUE", DISPATCH_QUEUE_SERIAL);
//参数一:C字符串 队列名
//参数二:队列中执行的方式 DISPATCH_QUEUE_SERIAL 串行 DISPATCH_QUEUE_CONCURRENT并行
//2.在队列中管理一个异步操作
dispatch_async(myQueue, ^{
for (int i = 0; i < 5; i++) {
NSLog(@"我爱你中国!");
}
});
dispatch_async(myQueue, ^{
for (int i = 0; i < 5; i++) {
NSLog(@"打死小日本");
}
});
dispatch_async(myQueue, ^{
NSLog(@"执行结束!");
});
//总结:如果一个队列设置的执行方式是串行 使用GCD异步执行 不会影响队列内部执行的顺序
dispatch_queue_t mainQueue = dispatch_get_main_queue();
/*
dispatch_suspend(myQueue);//暂停一个队列
//如果暂停一个队列不要忘记恢复。暂停和恢复的操作和内存管理中的retain和release类似。调用dispatch_suspend会增加暂停计数,而dispatch_resume则会减少。队列只有在暂停计数变成零的情况下才开始运行。
dispatch_resume(myQueue);//恢复一个队列如果不恢复程序会崩溃
*/
dispatch_queue_t queue = dispatch_queue_create("com.test.gcd", DISPATCH_QUEUE_SERIAL);
//提交第一个block,延时5秒打印。
dispatch_async(queue, ^{
sleep(5);
NSLog(@"After 5 seconds...");
});
//提交第二个block,也是延时5秒打印
dispatch_async(queue, ^{
sleep(5);
NSLog(@"After 5 seconds again...");
});
//延时一秒
NSLog(@"sleep 1 second...");
sleep(1);
//挂起队列
NSLog(@"suspend...");
dispatch_suspend(queue);
//延时10秒
NSLog(@"sleep 10 second...");
sleep(10);
//恢复队列
NSLog(@"resume...");
dispatch_resume(queue);
// 主线程执行:多用户返回主线程
dispatch_async(dispatch_get_main_queue(), ^{
// something
});
// 一次性执行:例如单例
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// code to be executed once
});
另外GCD多线程可以处理程序耗时操作防治程序假死,例如下载文件
GCD的另一个用处是可以让程序在后台较长久的运行。
在没有使用GCD时,当app被按home键退出后,app仅有最多5秒钟的时候做一些保存或清理资源的工作。但是在使用GCD后,app最多有10分钟的时间在后台长久运行。这个时间可以用来做清理本地缓存,发送统计数据等工作。