-
基本概念
-
主线程
一个iOS程序运行以后,默认会开启一个线程,这个线程就被称为主线程或(UI线程)。主线程的主要作用是显示\刷新UI界面,处理UI事件(点击,滚动,拖拽等)。
-
iOS中的多线程
- Pthread:基本不使用了
- NSThread:每个Thread对象对应一个线程,使用较少,线程的生命周期由我们自己管理
- GCD:基于C语言的框架,可以充分利用多核,苹果推荐使用,生命周期由系统管理
- NSOperation:基于GCD来实现,对GCD进行了封装,生命周期由系统管理
-
-
NSThread
-
创建
eg:NSThread *thread = [[NSThread alloc] initWithTarget: self selector: @selector(loadImage:) object: @(i)];
-
常用属性
- name:进程名称
- threadProiority:进程的优先级
-
常用方法
- + (NSThread *)currentThread; 返回当前进程
- + (void)sleepForTimeInterval: (NSTimeInterval) ti; 当前进程暂停一个时间戳
- + (void)exit; 销毁当前进程
- + (NSThread *)mainThread; 返回主线程
- - (void)cancel; 取消当前任务
- - (void)start; 开始当前进程
-
对NSObject的扩展—同多线程相关
- performSelectorOnMainThread: …… 使当前实例方法在主线程中执行
- performSelector: (SEL)aSelector onThread: thr 使aSelector方法在thr线程中执行
- performSelector: (SEL)aSelector withObject: …… 在新的线程中调用目标selector自动指定线程
-
-
GCD
- dispatch_queue_t mainQueue = dispatch_get_main_queue(); 获取主队列并赋值给mainQueue变量,主队列:是串行队列
-
dispatch_queue_t globalQueue = dispatch_get_global_queue(0, DISPATCH_QUEU_PRIORITY_DEFAULT); 获取全局队列(并行队列)并赋值
参数"0":标识符
参数"DISPATCH_QUEU_PRIORITY_DEFAULT":优先级,这值表示:默认值
优先级有:
DISPATCH_QUEU_PRIORITY_HIGH 2
DISPATCH_QUEU_PRIORITY_DEFAULT 0
DISPATCH_QUEU_PRIORITY_Low -2
DISPATCH_QUEU_PRIORITY_BACKGROUND INT16_MIN
-
自定义队列
-
自定义串行队列
dispatch_queue_t queue1 = dispatch_queue_create("queue1", DISPATCH_QUEUE_SERIAL);
参数" queue1":标识符
参数"DISPATCH_QUEUE_SERIAL":创建当前队列为串行队列
-
自定义并行队列
dispatch_queue_t queue2 = dispatch_queue_create("queue2", DISPATCH_QUEUE_CONCURRENT);
参数" queue2":标识符
参数"DISPATCH_QUEUE_ CONCURRENT":创建当前队列为并行队列
-
-
同步提交/同步任务
dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
-
异步提交/异步任务
dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
-
串/并队列+同/异任务 执行效果
同步任务
异步任务
主队列(串行队列)
同步任务未执行,出现阻塞(阻塞UI更新)
顺序执行,在主线程中,未开启新线程
全局队列(并行队列)
顺序执行,在主线程中,未开启新线程
同时执行,每个异步任务都开启了新线程
自定义串行队列
顺序执行,在主线程中,未开启新线程
顺序执行,开启一个新线程,所有任务均在这个线程中执行
自定义并行队列
顺序执行,在主线程中,未开启新线程
同时执行,每个异步任务都开启了新线程
顺序执行(依次执行):先执行完先进去的任务,然后再执行下一个任务
同时执行(无序执行):多个任务交替执行,因优先级不确定,所以执行顺序凌乱。因CPU执行速度很快,在多个线程中轮流执行多个任务,造成了一种同时执行的假象。
总结:
- 先看是什么任务,再看是什么队列,才能决定任务怎么执行
- 主队列除外,同步/异步任务决定是否开启新线程
- 串行/并行队列决定任务的执行方式,是顺序执行(开启新的单条线程),还是同时执行(开启新的多条线程)
- 任何队列的同步任务,都会顺序执行,并且未开启新线程
- 任何任务的主队列,都不会开启新线程,而在主线程中执行。同步任务(阻塞),异步任务(顺序执行)
- 常使用任意队列异步任务来执行;更新UI,使用主队列异步任务
-
NSOperation
-
NSOperation(操作类父类,抽象类,不做具体事情)
- - (void) start; 开始"操作任务"
- - (void)cancel; 取消"操作任务"
- - (void)addDependancy: (NSDperation *)op; 添加依赖关系
- - (void)removeDependency: (NSDeperation *)op; 移除依赖关系
-
属性queuePriority:"操作任务"在队列中的优先级,在属性maxConcurrentOperationCount为1时,此属性的效果才会体现出来
NSDperationQueuePriorityVeryLow = -8L 很低
NSDperationQueuePriorityLow = -4L 低
NSDperationQueuePriorityNormal = 0 正常
NSDperationQueuePriorityHeight = 4 高
NSDperationQueuePriorityVeryHeight 很高
-
NSInvocationOperation(操作类子类,做具体的事情)
- start方法:在主线程执行,先执行完上一个任务,再执行下一个任务,顺序执行
- 添加到NSOperationQueue执行队列中,每个任务都被系统放置在没有使用的线程中,同时执行
-
NSBlockOperation(操作类子类,做具体的事情)
- start方法:在主线程中,顺序执行
- 添加到NSOperationQueue执行队列中,每个任务都被系统放置在没有使用的线程中,同时执行
- 实例方法addExeautionBlock添加block任务到操作中每个任务都被系统放置在没有使用的线程中,同时执行
-
NSOperationQueue(操作队列类,存放操作对象)
- 属性maxConcurrentOperationCount:最大并发数(同一时间执行的任务数)
- - (void)cancelAllOperations; 取消所有"操作任务"
-
总结
- NSInvocationOperation同NSBlockOperation执行效果一样
- NSInvocationOperation任务是要传入方法,而NSBlockOperation任务则要传入block代码块。NSBlockOperation更实用
-
问题
- NSOperationQueue属性suspended设置无效果,不能实现队列的暂停和重新开始
- NSOperationQueue的cancel方法能够实现取消任务
-
-
线程安全
全局变量、静态变量、属性、公有变量、单例,在被多个线程访问时,会导致线程安全(多线程同时访问变量,会使各个之间的操作的结果出现矛盾)
解决方案:
第一种:synchronized同步锁
例如:synchronized(self){
//放置操作变量的代码
}
第二种:GCD的只执行一次同步锁
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//放置只执行一次的代码
})
iOS学习之路05 - 多线程编程
最新推荐文章于 2022-12-11 17:57:48 发布