浅谈iOS多线程
浅谈iOS多线程
首先,先看看进程和线程的概念。
图1.1
这一块不难理解,重点点下他们的几个重要区别:
1,地址空间和资源:进程可以申请和拥有系统资源,线程不行。资源进程间相互独立,同一进程的各线程间共享。某进程内的线程在其它进程不可见。
2,通信:进程间需要用到IPC(这个可以谁总结开个课),线程可以直接读写进程的数据段来通信(需要涉及锁,下面会简单讲到)。
3,调度和切换:线程快,进程慢。
好了,切回主题,iOS多线程技术,一般有三个,NSThread,NSOperation/NSOperationQueue,GCD(Grand Central Dispatch),好,首先先抛出一些概念。
NSThread
- 使用NSThread对象建立一个线程非常方便。
- 但是!要使用NSThread管理多个线程非常困难,不推荐使用。
- 技巧!使用[NSThread currentThread]跟踪任务所在线程,适用于这三种技术。
NSOperation/NSOperationQueue
- 是使用GCD实现的一套Objective-C的API。
- 是面向对象的线程技术。
- 提供了一些在GCD中不容易实现的特性,如:限制最大并发数量、操作之间的依赖关系。
- 苹果官方现在建议大家使用该多线程技术,但现在仍然很多人使用GCD技术,因为GCD使用较为方便。
GCD —— Grand Central Dispatch
- Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法,称作大中心调度。该方法在Mac OS X 10.6雪豹中首次推出,并随后被引入到了iOS4.0中。GCD是一个替代诸如NSThread, NSOperationQueue, NSInvocationOperation等技术的很高效和强大的技术。
- 是基于C语言的底层API。
- 用Block定义任务,使用起来非常灵活便捷。
- 提供了更多的控制能力以及操作队列中所不能使用的底层函数。
以上就是对于这三种技术的简单介绍,接着再来介绍下几个基本的概念,
队列:队列是先进先出(FIFO)结构的,在iOS中,队列主要的任务是负责线程的创建、回收工作,不论什么队列和什么任务都不需要程序员参与,减轻了程序员的工作。有GCD队列和自定义队列。根据这些,我们实际上可以操作四种队列,全局队列,主队列,串行队列,并行队列。
任务:分为同步任务和异步任务。同步任务:必须按照顺序执行的任务,异步任务:执行顺序不一定,哪个先抢占到资源哪个先执行(我试过将多个异步任务并发执行,系统会将这些任务分配给若干个线程,然后由线程调度执行,分配到同一线程的任务还是按顺序执行的)。
于是乎,将这些队列和任务组合,就会出现8种组合,赶紧投票吧,分享会上用代码来详细讲解下这8种组合的效果。
下面简单介绍下以上三个技术在代码中的使用:
NSThread 使用它经常是用来查看当前线程:[NSThread currentThread](用来判断是否在主线程执行也很方便),因为其他的确实不好用,也不推荐用。
NSOperation/NSOperationQueue 虽说是苹果基于GCD实现的面相对象的线程技术,但是感觉用起来没有GCD方便,下面简单介绍下它的几个用法
NSOperation 对应任务 有以下三种用法
1 NSInvocationOperation
2 NSBlockOperation
3 自定义NSOperation 子类
1 和 2 我给出初始化方法 大家就一眼能知道区别和用法了。
NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(task) object:nil];// 调用start方法执行操作op操作
[op start];
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"task0---%@", [NSThread currentThread]);
}];
[op start];
恩 其实就是调用的是block还是方法的区别了。注意 start后是指在当前线程同步执行任务。
自定义子类也说下
主要操作就是继承NSOperation,然后在.m文件中实现- (void)mian方法,然后运行start的时候就会运行main方法里的代码。
另外 任务提供执行完成的回调
op.completeBlock可以监听一个操作执行完毕的时刻,这个block里面可以添加一些我们需要执行的操作,这个block里面的操作仍然是在子线程执行,但不一定和被监听的操作在同一个线程
接着讲下NSOperationQueue
NSOperationQueue 对应队列 且是并行队列。
先解决个疑惑,如何使用串行队列?NSOperationQueue提供了一个设置最大并发数的方法setMaxConcurrentOperationCount: 只要将最大并发数设置为1,就是串行队列了。
首先 NSOperationQueue 可以获取到主队列 或者自己创建。
NSOperationQueue 提供 addOperation和addOperationWithBlock方法 名字取得很好,一眼就可以看出用法了,前者用来添加任务,后者用block的方式来添加任务。
同时提供cancal单个任务和cancelAllOperations所有任务的方式,不能cancel正在执行的任务。
同时提供获取挂起状态和设置挂起状态的方法。
isSuspended : 判断是否挂起
setSuspended: YES表示挂起,NO表示恢复
同样 不能对正在执行的任务设置。
任务间的执行先后,可以设置依赖来排序。
[op2 addDependency:op1];
Op1执行完成后才执行op2.
其实简单的操作用NSOperation比起GCD来要美观一下,个人感觉。
最后讲重点GCD 我觉得它之所以强大是因为它提供了不止前面这些功能还提供了一些常用的额外功能,下面我来一一讲解。
几个简单的和前面功能类似的
dispatch_get_global_queue全局队列并行队列
dispatch_get_main_queue主队列主线程中的唯一队列
dispatch_queue_create自定义队列DISPATCH_QUEUE_SERIAL串DISPATCH_QUEUE_CONCURRENT并行
dispatch_sync 同步线程
dispatch_async 异步线程
这些用法和前面类似 到时8个组合用GCD简单演示下,相当于两个一起理解了。
之所以说GCD比NSOperation强大,就是他不仅能实现NSOperation能实现的,还有很多很好用的方法,下面一一讲解:
dispatch_once 一次性代码 使用dispatch_once保证代码只被执行一次 使用场景:单例对象的初始化 这个大家接触的很多了 不多讲了
dispatch_group_t 队列组 使用这个可以很好的控制任务调度
我们经常有需求 需要在一个页面请求多个接口 当多个接口都完成后执行刷新UI的操作 这个时候我们的操作一般都是多个异步返回的时候各自判断 其实用dispatch_group_t 可以很好的解决这个问题
思路如下
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 异步取数据A
});
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 异步取数据B
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// 等前面的异步操作都执行完毕后,回到主线程刷新UI
});
dispatch_group_notify是队列组中所有任务都完成后会发送的通知。
思考下:我们的业务场景经常能用到这个思路,大家有没例子的?
dispatch_after 这个其实也挺经常用到的 延迟执行方法 网上说只是延迟提交,并不是延迟立刻执行 会有些许的时间差。
dispatch_barrier_async 确保提交的闭包是指定队列中在特定时段唯一在执行的一个 这个可以当锁用。
//创建队列
self.isolationQueue = dispatch_queue_create([label UTF8String], DISPATCH_QUEUE_CONCURRENT);
//改变setter
- (void)setCount:(NSUInteger)count forKey:(NSString *)key
{
key = [key copy];
//确保所有barrier都是async异步的
dispatch_barrier_async(self.isolationQueue, ^(){
if (count == 0) {
[self.counts removeObjectForKey:key];
} else {
self.counts[key] = @(count);
}
});
}
这是网上找的代码 实际上synchronized可以更好的完成这个锁操作,这是后话啦,有空再分析这个。实际上他的用法也比较多,到时搞个demo分享下。
dispatch_apply 可进行快速迭代
用来替换对前一次计算没有依赖的for循环会优化很多,例如
for (int i = 0; i < 999 ; i++) {
dispatch_async(concurrentQueue, ^{
NSLog(@"wrong %d",i);
//do something hard
});
}
改用dispatch_apply 来处理
dispatch_apply(999, concurrentQueue, ^(size_t i){
NSLog(@"correct %zu",i);
//do something hard
});
Dispatch IO 文件操作
用到的方式是多个线程去读取不同的数据块,然后再合并。
Dispatch source 这个也是程序优化的一道利器,且支持多种场景,对于程序优化很有帮助,这块可以大力研究下,用Dispatch source来取代一些回调函数可以有效的提高程序执行的效率,codereview下我们的代码,应该有能够用上这块的(到时奉上)。
Dispatch Semaphore这个类似于操作系统中的信号量,可以用来解决死锁的问题。这个其实是个很有趣的领域,
dispatch_semaphore_wait等待信号量需要dispatch_semaphore_signal执行后才能跳过。配合使用可以解决很多复杂的线程问题。
发挥下想象力:通过这个信号量,是不是用很好的方式解决我们请求等待同步的问题?
最后稍微讲下锁
建议使用synchronized就可解决大部分的问题了 给出ElearningConfig中的代码示例
实际上就是这段被{}包起来的代码只会被一个线程调用,而锁就是self对象。意思就是,执行代码块的时候会对self上锁,当下一个线程需要对代码块调用时,需要等待上一个程序解锁self才可以。
好啦,更多精彩内容,我们分享会见!
浅谈iOS多线程的更多相关文章
- 浅谈iOS视频开发
浅谈iOS视频开发 这段时间对视频开发进行了一些了解,在这里和大家分享一下我自己觉得学习步骤和资料,希望对那些对视频感兴趣的朋友有些帮助. 一.iOS系统自带播放器 要了解iOS视频开发,首先我们从 ...
- 浅谈iOS中的userAgent
浅谈iOS中的userAgent User-Agent(用户代理)字符串是Web浏览器用于声明自身型号版本并随HTTP请求发送给Web服务器的字符串,在Web服务器上可以获取到该字符串. 在公司产 ...
- 浅谈iOS需要掌握的技术点
鉴于很多人的简历中的技术点体现(很多朋友问我iOS需要知道注意哪些)! 技术点: 1.热更新 (及时解决线上问题) 2.runtime(json解析.数据越界.扩大button点击事件.拦截系统方法) ...
- 浅谈iOS中MVVM的架构设计与团队协作
说到架构设计和团队协作,这个对App的开发还是比较重要的.即使作为一个专业的搬砖者,前提是你这砖搬完放在哪?不只是Code有框架,其他的东西都是有框架的,比如桥梁等等神马的~在这儿就不往外扯了.一个好 ...
- IOS中 浅谈iOS中MVVM的架构设计与团队协作
今天写这篇文章是想达到抛砖引玉的作用,想与大家交流一下思想,相互学习,博文中有不足之处还望大家批评指正.本篇文章的内容沿袭以往博客的风格,也是以干货为主,偶尔扯扯咸蛋(哈哈~不好好工作又开始发表博客啦 ...
- 浅谈 iOS 与 H5 的交互- JavaScriptCore 框架
前言 小的作为一个iOS程序猿,可能研究JavaScript以及H5相关的知识并不是为了真正的要去转行做这一方面,其实更多的为了要研究OC中的JavaScriptCore框架,JavaScriptCo ...
- 浅谈iOS中MVVM的架构设计与团队协作【转载】
今天写这篇文章是想达到抛砖引玉的作用,想与大家交流一下思想,相互学习,博文中有不足之处还望大家批评指正.本篇文章的内容沿袭以往博客的风格,也是以干货为主,偶尔扯扯咸蛋(哈哈~不好好工作又开始发表博客啦 ...
- 浅谈iOS开发的协议(protocol)和代理(delegate)
协议和代理对于一个新手来说确实不讨好理解,也有很多的iOS开发的老手对此是懂非懂的.网上的很多博文只是讲了怎么使用,并没有说的很明白.下面我谈一下我的理解. 1.你要先搞明白,协议和代理为什么会出现, ...
- 浅谈iOS程序员的成长和进阶
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,bi ...
随机推荐
- 整合SSM框架应用
普通方式 新建spring模块时引入如下内容: 启用devtools插件(热部署插件) idea需要做如下配置 settings-build-compiler->勾选build project ...
- 最小生成树-Borůvka算法
一般求最小生成树的时候,最流行的是Kruskal算法,一种基于拟阵证明的贪心,通过给边排序再扫描一次边集,利用并查集优化得到,复杂度为\(O(ElogE)\).另一种用得比较少的是Prim算法,利用优 ...
- 【uoj#207】共价大爷游长沙 随机化+LCT维护子树信息
题目描述 给出一棵树和一个点对集合S,多次改变这棵树的形态.在集合中加入或删除点对,或询问集合内的每组点对之间的路径是否都经过某条给定边. 输入 输入的第一行包含一个整数 id,表示测试数据编号,如第 ...
- Java虚拟机的内存管理----垃圾收集器
1.Serial收集器 优点,是简单而高效,单线程避免了线程交互的开销. 缺点,进行垃圾回收时需要Stop the world(暂停所有用户线程). 2.ParNew收集器 它是Serial收集器的多 ...
- Qin Shi Huang's National Road System UVA - 1494(次小生成树)
秦始皇统一中国之后要在全国修公路连接各个城市,皇帝只想修成最小生成树(距离最小,不考虑人力),一个道士说自己可以不花人力物力修一条路,经过两方妥协,选择max(两个城市人口/(生成树长度-这条路的长度 ...
- ACID和CAP, BASE
ACID:关系型数据库中事务的4个属性: Atomicity,原子性,整个事务的所有操作,要么全部完成,要么全部不完成,不可能停滞在中间的某个环节.事务在执行过程中出错,会回滚到事务开始前的状 ...
- Hyperledger Fabric 实战(十二): Fabric 源码本地调试
借助开发网络调试 fabric 源码本地调试 准备工作 IDE Goland Go 1.9.7 fabric-samples 模块 chaincode-docker-devmode fabric 源码 ...
- 【BZOJ4889】不勤劳的图书管理员(树套树)
[BZOJ4889]不勤劳的图书管理员(树套树) 题面 又是权限题,烦死了 洛谷真好 题解 分开考虑每一次交换产生的贡献. 假设交换\((x,y)\) 检查\(x\)与\(y\)对于区间\([x+1, ...
- WlanGetAvailableNetworkList
原文msdn链接地址:https://docs.microsoft.com/zh-cn/windows/desktop/api/wlanapi/nf-wlanapi-wlangetavailablen ...
- struts的status属性
struts2 <s:iterator> status属性 转载▼ iterator标签主要是用于迭代输出集合元素,如list set map 数组等,在使用标签的时候有三个属性值得我 ...