关于多线程编程首先我们要了解清楚什么是线程,什么是进程,以及他们之间的区别和联系。
所谓的线程就是CPU调度(执行任务)的最小单位,其实就是一段代码。
而进程是CPU分配资源和调度的单位,说明白点就是系统中正在运行的一个应用程序。
两者的联系和区别
线程是进程的组成部分,一个进程可以开启多个子线程,但是每一个进程至少需要有一个线程;
一个进程的所有任务都是在线程中执行的
同一个进程内的线程共享进程的资源
多线程的概念和原理
概念:一个程序开启多条线程,每条线程可以并行(同时)执行不同的任务
原理:(1)多个线程并发执行,其本质就是CPU快速地在多条线程之间切换。(2)当CPU调度线程的时间足够快,就会造成多线程并发执行的假象。
那么了解了这么多,我们学习多线程开发主要是为了什么呢?
简单来说一下多线程的优缺点
优点:能适当地提高程序的执行效率,能适当提高资源利用率(CPU和内存利用率)
缺点:创建多线程是有开销的,包括内存空间和创建时间上的开销,如果开启大量的线程,会导致程序性能降低,线程越多,CPU在调度线程上的开销就越大
到底什么是主线程,以及他有什么作用,下面让我们一起探索一下
定义:iOS程序运行后,默认开启一条线程,称为多线程
作用:显示或刷新UI界面,处理UI事件
注意:不要将耗时操作放到主线程,耗时操作会卡死主线程,影响UI界面性能
实现多线程的方法主要有哪些?以及他们有哪些特点
NSThread:(偶尔OC)使用更加面向对象,简单易用,可直接操作线程对象
GCD:(经常C)旨在替代NSThread等线程技术,充分利用设备的多核
NSOperation:(经常OC)基于GCD,比GCD多了一些更简单实用的功能,使用更加面向对象
项目中一般在哪用到多线程?
多线程一般用于耗时操作,如:网络请求、上传,下载文件、读取数据库、文件操作、大循环
什么是线程安全问题?有什么解决方案?
定义:多个线程同时访问同一块资源(例如同一个对象、变量、文件)时,引发的数据错乱和数据安全问题,称为线程安全问题
解决方法:1.添加互斥锁;2.互斥锁的使用格式 :@synchronized( 锁对象 ){ //需要锁定的代码};3.加锁的原理:使线程同步执行
FMDB是线程安全的么?
FMDB如果使用FMDatabase类是线程不安全的
使用FMDatabaseQueue是线程安全的
线程通信的概念,如何实现?
概念:一个线程传递数据给另一个线程、一个线程中执行完特定任务后,转到另一个线程继续执行任务
实现方法:
performSelectorOnMainThread和performSelectorOnThread方法
performSelectorInBackground(后台线程中执行)
使用GCD的dispatch方法
GCD内部怎么实现的,使用GCD有什么优势?
实现方式:
1.通过定制任务和将任务添加到队列中来实现GCD的多线程功能
2.GCD会自动将队列中的任务去出来,放到对应的线程中执行
3.任务的取出遵循FIFO原则(先进先出)
优势:
1.会自动利用更多的CPU内核
2.会自动管理线程的生命周期
全局并发队列和使用create函数创建的并发队列有什么区别?
1.全局并发队列在整个程序中本身是默认存在的,并且对应有高优先级,默认优先级,低优先级,后台优先级一共四种并发队列,我们只是选择其中一个来用,而使用create函数创建的并发队列是实打实地从头开始去创建一个队列
2.iOS6之前,使用create函数创建的队列都要进行一次Release,而全局并发队列不需要我们手动Release。但在iOS6之后,GCD已经纳入ARC内存操作中,不需要再进行Release
3.使用栅栏函数时,使用全局并发队列是无效的,只有使用create创建的并发队列才有效(特别需要注意)
GCD中如何控制多线程并发执行时的执行顺序
使用栅栏函数dispatch_barrier_async
GCD除了开线程,还可以用在什么地方?
1.单例:一次函数dispatch_once
2.延迟函数:dispatch_after,可以定义执行任务的线程
3.定时器:dispatch_source_set_event_handler
4.快速迭代:dispatch_apply
GCD快速迭代的定义和作用?
定义:同时开启主线程和子线程并发完成循环操作
作用:大大提高循环操作的效率
GCD中队列组的作用
使用队列组,除了可以开启新的线程,同时还能通过group监听队列中任务的执行情况
如何处理GCD造成的死锁问题
1.将队列改为非主队列
2.将调度方式改为异步调度
NSOperation和GCD的区别?
1.实现机制的区别:
(1).使用这两者执行任务都会由系统自动创建、销毁子线程
(2).GCD底层是基于C语言的,NSOperation则是对GCD的封装,是面向对象的
(3).NSOperation只有两种类型的队列,主队列和非主队列(非主队列既可以是并行的也可以是串行的,默认是并行的)
(4).GCD拥有四种类型的队列 (main, global, create[serial], create[concurrent] )
2.使用上的区别:
(1).GCD的使用更轻量级,而NSOperation作为对象提供了更丰富的API
(2).在NSOperationQueue中,可以随时取消要准备执行的任务,而GCD没法停止已经加入queue的block中的任务
(3).KVO能应用在NSOperation中,以监听一个Operation是否完成或取消,这样能比GCD更加有效地掌控我们执行的后台任务
(4).NSOperation通过继承,可以提高代码的复用度,这比GCD更有自由度和扩展性
(5).同一个并行队列中的任务执行时,我们能够设置NSOperation的priority(优先级),使之按顺序执行,而在GCD中,要使block中的任务实现这个功能,需要大量复杂代码
什么是最大任务并发数?NSOperationQueue中如何操纵队列中的任务?
线程的最大任务并发数:异步执行时同一时间内可以同时执行的操作的最大数
当maxConcurrentOperationCount = 1,只能执行一个操作,队列为串行队列
当maxConcurrentOperationCount = 0,无法执行任何操作
当maxConcurrentOperationCount > 1,队列为并发队列
默认条件下maxConcurrentOperationCount = -1,代表最大并发数没有限制
NSOperationQueue处理A,B,C三个线程,要求执行完A,B后才能执行C,怎么做?
添加依赖关系,AB都依赖C
- (void)operation{
NSOperationQueue*queue = [[NSOperationQueuealloc] init];
NSBlockOperation*opA = [NSBlockOperationblockOperationWithBlock:^{
NSLog(@"A----%@",[NSThreadcurrentThread]);
}];
NSBlockOperation*opB = [NSBlockOperationblockOperationWithBlock:^{
NSLog(@"B----%@",[NSThreadcurrentThread]);
}];
NSBlockOperation*opC = [NSBlockOperationblockOperationWithBlock:^{
NSLog(@"C----%@",[NSThreadcurrentThread]);
}];
//注意:不能互相依赖
[opC addDependency:opA];
[opC addDependency:opB];
[queue addOperation:opA];
[queue addOperation:opB];
[queue addOperation:opC];
NSLog(@"----end----");
}
有一个需求,需要将N个请求全部完成之后执行某个操作,该如何处理
1.GCD中可以使用栅栏函数或者队列组
2.NSOperation中可以添加依赖关系
网友评论