iOS开发基础36-多线程之GCD
1.iOS开发基础1-第一个iOS程序2.iOS开发基础2-基础控件3.iOS开发基础6-懒加载、Plist 文件操作、字典转模型、自定义 View 详解4.iOS开发基础5-UIButton5.iOS开发基础4-图像资源6.iOS开发基础3-UIImage7.iOS开发基础14-KVC的应用与底层逻辑8.iOS开发基础13-深入理解 UITableView(二)9.iOS开发基础12-深入理解UITableView(一)10.iOS开发基础11-屏幕适配、Autolayout及 Masonry 框架11.iOS开发基础10-UIButton内边距和图片拉伸模式12.iOS开发基础9-提示框(UIAlertController)13.iOS开发基础8-UIScrollView14.iOS开发基础7-自定义构造方法、layoutSubviews、Xib文件与自定义View15.iOS开发基础30-UITabBarController16.iOS开发基础29-触摸事件及手势识别17.iOS开发基础28-数据存储与沙盒机制18.iOS开发基础27-导航控制器入栈与出栈机制及微博个人详情页19.iOS开发基础26-空20.iOS开发基础25-ARC和MRC深入探析21.iOS开发基础24-UIPickerView、UITextField、KVC、UIDatePicker、控制器及导航控制器22.iOS开发基础23-iOS开发中的Info.plist、UIApplication及其Delegate、UIWindow详解23.iOS开发基础22-键盘通知在iOS开发中的应用24.iOS开发基础21-深入理解通知、代理、KVO和Block在iOS开发中的应用25.iOS开发基础20-UITableView的全局及局部刷新、左滑操作与批量删除26.iOS开发基础19-深入理解和实现不等高的 UITableViewCell27.iOS开发基础18-深入理解 Objective-C Runtime 机制28.iOS开发基础16-使用 `NSTimer` 时避免内存泄露的技巧和最佳实践29.iOS开发基础15-KVO的应用与底层逻辑30.iOS开发基础65-iPad 开发指南31.iOS开发基础64-二维码32.iOS开发基础63-AVFoundation/MediaPlayer33.iOS开发基础62-音频播放34.iOS开发基础61-通讯录35.iOS开发基础60-传感器36.iOS开发基础59-内存优化37.iOS开发基础58-支付宝集成指南38.iOS开发基础57-换肤功能与静态库开发指南39.iOS开发基础56-UIDynamic物理引擎40.iOS开发基础55-利用 UIWindow 实现快速滚动到界面顶部41.iOS开发基础54-CoreLocation42.iOS开发基础53-MapKit 框架43.iOS开发基础47-iOS键盘44.iOS开发基础46-数据安全与HTTPS保护详解45.iOS开发基础45-UIWebview46.iOS开发基础44-网络编程之NSURLSession&AFN47.iOS开发基础43-CocoaPods48.iOS开发基础42-网络编程之文件下载与处理49.iOS开发基础41-网络编程之JSON和XML50.iOS开发基础40-网络编程之NSURLConnection51.iOS开发基础39-RunLoop52.iOS开发基础38-多线程之多图片下载及缓存处理53.iOS开发基础37-多线程之NSOperation
54.iOS开发基础36-多线程之GCD
55.iOS开发基础35-多线程之NSThread56.iOS开发基础34-多线程57.iOS开发基础33-核心动画(二)58.iOS开发基础33-核心动画(一)59.iOS开发基础32-Quartz2D(二)60.iOS开发基础32-Quartz2D(一)61.iOS开发基础31-Modal 与 Push 详解62.iOS开发基础76-iOS 开发中的属性修饰符详解63.iOS开发基础75-iOS开发中的Block深度解析64.iOS开发基础74-Swift他来了65.iOS开发基础73-24种性能优化技巧66.iOS开发基础72-Xcode 7 升级后的问题与解决方案详解67.iOS开发基础71-应用中的 StatusBar 详解68.iOS开发基础70-TCP与UDP69.iOS开发基础69-应用开发中的 Controller 间通信模式70.iOS开发基础68-图片轮播71.iOS开发基础67-流水布局相册缩放72.iOS开发基础66-UISearchBar 控件指南73.iOS开发基础78-iOS 国际化在现代 iOS 开发中,利用多核处理器来提升应用的性能和响应速度是至关重要的。苹果公司推出的 GCD(Grand Central Dispatch),提供了一套强大的并发编程框架,使得开发者能够轻松实现多线程操作。本文将详细介绍 GCD 的基本概念、任务和队列、执行任务的方式、队列的创建、线程间通信、以及其他高级用法及单例模式的实现。
一、基本概念
1. 简介
什么是 GCD
GCD,全称 Grand Central Dispatch,可译为“牛逼的中枢调度器”。它是一套基于 C 语言的底层 API,提供了非常多强大的函数,用来处理并发任务的分发和执行。
GCD 的优势
- 多核优化:GCD 自动利用设备的多核 CPU(如双核、四核等)。
- 线程管理:GCD 自动管理线程的生命周期,包括创建、调度和销毁线程。
- 简化代码:开发者只需定义需要执行的任务,并将其添加到相应的队列,无需编写复杂的线程管理代码。
2. 任务和队列
GCD 中有两个核心概念:任务和队列。
- 任务:具体执行的操作。
- 队列:用于存放任务。
GCD 的使用通常分为两个步骤:
- 定制任务:确定需要执行的操作。
- 将任务添加到队列中:GCD 会按照 FIFO 原则自动将队列中的任务取出,并放到对应的线程中执行。
二、执行任务
1. 执行任务的函数
同步执行任务
dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
- queue:队列
- block:任务
异步执行任务
dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
同步和异步的区别
- 同步:只能在当前线程中执行任务,不具备开启新线程的能力。
- 异步:可以在新的线程中执行任务,具备开启新线程的能力。
2. 栅栏函数
dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t block);
- 栅栏函数会在前面的任务执行完毕后执行其内部任务,然后再执行其后的任务。
- 栅栏函数必须和普通任务在同一个串行或并发队列中执行,不能用于全局并发队列。
3. 队列的类型
- 并发队列(Concurrent Dispatch Queue):可以让多个任务并发(同时)执行。
- 串行队列(Serial Dispatch Queue):一个任务执行完毕后,再执行下一个任务。
4. 容易混淆的术语
- 同步 vs 异步:影响是否能开启新线程。
- 并发 vs 串行:影响任务执行方式。
三、创建队列
1. 并发队列
通过 dispatch_queue_create
函数创建并发队列:
dispatch_queue_t queue = dispatch_queue_create("com.example.queue", DISPATCH_QUEUE_CONCURRENT);
2. 全局并发队列
使用 dispatch_get_global_queue
函数获取全局并发队列:
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
全局并发队列在 iOS 8 以后使用服务质量(QoS)来决定优先级:
- QOS_CLASS_USER_INTERACTIVE:用户交互,优先级最高
- QOS_CLASS_USER_INITIATED:用户需要
- QOS_CLASS_DEFAULT:默认优先级
- QOS_CLASS_UTILITY:工具类,适合耗时操作
- QOS_CLASS_BACKGROUND:后台
3. 串行队列
通过 dispatch_queue_create
函数创建串行队列:
dispatch_queue_t queue = dispatch_queue_create("com.example.serialQueue", NULL); // 或者 DISPATCH_QUEUE_SERIAL
主队列(主线程相关):它是 GCD 自带的一种特殊串行队列,任务在主线程中执行:
dispatch_queue_t queue = dispatch_get_main_queue();
四、线程间通信
从子线程回到主线程:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 处理耗时操作
dispatch_async(dispatch_get_main_queue(), ^{
// 回到主线程,执行UI刷新操作
});
});
五、其他用法
1. 延时执行
使用 GCD
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// 2 秒后执行的代码
});
2. 一次性执行
保证某段代码在程序运行期间只被执行一次:
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// 这里的代码只会执行一次
});
3. 快速迭代
使用 dispatch_apply
进行快速迭代:
dispatch_apply(10, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t index){
// 迭代任务,这段代码会执行 10 次
});
4. 队列组
先分别异步执行两个耗时操作,然后再执行一个回到主线程的操作:
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 第一个耗时操作
});
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 第二个耗时操作
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// 等到上面两个异步操作都执行完毕后,执行这里的代码
});
六、单例模式
1. 单例模式的作用和使用场合
在程序运行期间,单例模式保证某个类只有一个实例,并且该实例可以方便地被访问,常用于共享一份资源。
2. ARC 中单例模式的实现
定义一个全局的 static 实例
static id _instance;
重写 allocWithZone
方法
+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [super allocWithZone:zone];
});
return _instance;
}
提供一个类方法访问实例
+ (instancetype)sharedInstance
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [[self alloc] init];
});
return _instance;
}
实现 copyWithZone
方法
- (id)copyWithZone:(struct _NSZone *)zone
{
return _instance;
}
结语
GCD 是 iOS 开发中强大的并发编程工具。通过合理使用 GCD,开发者可以充分利用设备的多核 CPU 提升应用性能,同时简化线程管理逻辑。
将来的你会感谢今天如此努力的你!
版权声明:本文为博主原创文章,未经博主允许不得转载。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!