在深入学习 GCD 之前,建议先了解线程的基本知识,相关资料可参考:http://www.cnblogs.com/alunchen/p/5337608.html
1. 简介
GCD(Grand Central Dispatch)是一个苹果公司开发的多核编程解决方案,不仅支持 Objective-C,还支持 C 和 C++。GCD 引入了一些重要的概念,如工作单元、无痛后台处理和自动线程管理,这些概念在所有基于 C 的语言中都可用。
GCD 的核心概念之一是队列,它可以确保任务按顺序执行,特别适合处理非线程安全的 UIKit 组件。你可以使用系统提供的队列,也可以自定义队列。
GCD 队列遵循 FIFO(先进先出)原则。
2. Block 基础
在使用 GCD 之前,理解 Block 的使用至关重要。Block 是一种闭包,可以替代 Objective-C 中的委托模式或 C 中的回调函数。关于 Block 的详细信息,可参考:http://www.cnblogs.com/alunchen/p/5341057.html
3. 开启新线程与主线程
下面的示例展示了如何使用 GCD 开启一个新线程。需要注意的是,当执行 `doSomething()` 方法时,`startTime` 变量会被捕获并在 Block 内部使用。因此,在调用 `dispatch_async` 时,`startTime` 会被保留一次,并且 Block 内部会创建一个新的不可变变量来存储它。
-(void)doSomething {
NSDate *startTime = [NSDate date];
// 获取一个全局队列,优先级为 DISPATCH_QUEUE_PRIORITY_DEFAULT
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 开启异步线程
dispatch_async(queue, ^{
// 在这里执行耗时操作
NSDate *endTime = [NSDate date];
NSLog(@"完成时间:%f", [endTime timeIntervalSinceDate:startTime]);
});
}
上述代码创建了一个异步线程,但不能在异步线程中直接更新 UI。下面的示例展示了如何在异步线程完成后返回主线程进行 UI 更新。
-(void)doSomething {
NSDate *startTime = [NSDate date];
// 获取一个全局队列,优先级为 DISPATCH_QUEUE_PRIORITY_DEFAULT
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 开启异步线程
dispatch_async(queue, ^{
// 在这里执行耗时操作
dispatch_async(dispatch_get_main_queue(), ^{
// 在这里执行 UI 更新操作
});
});
}
4. 并发程序块 - Dispatch Group
如果一个异步线程需要执行多个耗时任务,可以使用 Dispatch Group 来提高执行效率。Dispatch Group 允许你将多个任务分组,并在所有任务完成后执行指定的回调。这可以通过 `dispatch_group_async` 和 `dispatch_group_notify` 函数实现。
-(void)doSomething {
NSDate *startTime = [NSDate date];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 开启异步线程
dispatch_async(queue, ^{
// 执行耗时操作
doSomething2();
// 定义 Dispatch Group
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{
// 执行其他耗时操作
doSomething3();
});
// 等待所有任务完成后再执行回调
dispatch_group_notify(group, queue, ^{
dispatch_async(dispatch_get_main_queue(), ^{
// 执行 UI 更新操作
doSomethingWithUI();
});
});
});
}