多线程:防止主线程堵塞,增加运行效率。
The term thread is used to refer to a separate path of execution for code.
The term process is used to refer to a running executable, which can encompass multiple threads.
线程用于指代一个独立执行的代码路径
进程用于指代一个可执行程序,他可以包含多个线程
进程:
正在进行中的程序被称为进程,负责程序运行的内存分配;每一个进程都有自己独立的虚拟内存空间
进程是并发执行的程序,在执行过程中分配和管理资源的基本单位,是一个动态概念,竟争计算机系统资源的基本单位。每一个进程都有一个自己的地址空间,即进程空间
进程又可有单线程进程与多线程进程两种。
线程:
线程是进程中一个独立的执行路径(控制单元),是进程的一部分,一个进程中至少包含一条线程,即主线程。
在网络或多用户环境下,一个服务器通常需要接收大量且不确定数量用户的并发请求,为每一个请求都创建一个进程显然是行不通的,——无论是从系统资源开销方面或是响应用户请求的效率方面来看。因此,操作系统中线程的概念便被引进了。一个没有线程的进程可以被看作是单线程的。
一个线程中任务的执行是串行的, 也就是说同一时间内一个线程只能执行一个任务
线程:主线程、非主线程。
主线程:
一个 iOS 程序运行后, 默认会开启一条线程, 成为"主线程"或者"UI 线程"
主线程的主要作用:
显示/刷新 UI 界面
处理 UI 事件(比如点击事件, 滚动事件, 拖拽事件)
主线程的注意点:
不要将比较耗时的操作放到主线程
耗时操作会卡住主线程, 严重影响 UI 的流畅度, 给用户一种 "卡"的坏体检
//获得主线程:
[NSThread mainThread];
//获得当前线程:
[NSThread currentThread];
判断是否为主线程:
// 类方法
BOOL isMainA = [NSThread isMainThread];
// 对象方法
BOOL isMainB = [thread isMainThread];
//返回值为1, 就是主线程
线程 进程区别、联系:
进程拥有一个完整的虚拟地址空间,不依赖于线程而独立存在;
线程是进程的一部分,没有自己的地址空间,与进程内的其他线程一起共享分配给该进程的所有资源。
线程可以有效地提高系统的执行效率,但并不是在所有计算机系统中都是适用的,如某些很少做进程调度和切换的实时系统。使用线程的好处是有多个任务需要处理机处理时,减少处理机的切换时间;而且,线程的创建和结束所需要的系统开销也比进程的创建和结束要小得多。最适用使用线程的系统是多处理机系统和网络系统或分布式系统。
一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。
每个iOS应用程序都有个专门用来更新显示UI界面、处理用户的触摸事件的主线程,因此不能将其他太耗时的操作放在主线程中执行,不然会造成主线程堵塞(出现卡机现象),带来极坏的用户体验。一般的解决方案就是将那些耗时的操作放到另外一个线程中去执行。
多线程
一个进程可以开启多条线程,每条线程可以并行执行不同的任务
多线程:多个线程并发执行的技术
多线程原理
同一时间,CPU 只能处理一条线程, 只有一条线程在工作
多线程并发执行,其实是 CPU 快速的在多条线程之间调度(切换)
如果 CPU 调度线程的时间足够快, 就造成了多线程并发执行的假象
老CPU不能做到多线程同时执行,而是在很短时间内来回切换,给我们造成假象;现在的多核CPU能同时执行线程。
iOS中多线程技术有4种:
NSThread
NSOperation
GCD(Grand Central Dispatch)
Pthreads
区别、使用
抽象由低到高,抽象高就越简单。
- NSThread经过苹果封装,完全面相对象,直接操控线程对象,生命周期需要手动管理。
- NSOperation多用于网络中。
- GCD多用于本机处理上,解析大数据,能自动管理线程的生命周期(创建线程、调度任务、销毁线程),完全不需要我们管理,且使用了block而更加方便、灵活。
多线程的好处:
(1)易于调度。
(2)提高并发性。
(3)开销少。创建线程比创建进程要快。
(4)利于充分发挥多处理器的功能。
进程和线程的关系:
(1)一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。
(2)资源分配给进程,同一进程的所有线程共享该进程的所有资源。
(3)处理机分给线程,即真正在处理机上运行的是线程。
(4)线程在执行过程中,需要协作同步。不同进程的线程间要利用消息通信的办法实现同步。线程是指进程内的一个执行单元,也是进程内的可调度实体.
进程与线程的区别:
(1)调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位
(2)并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可并发执行
(3)拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源
(4)系统开销:在创建或撤消进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建或撤消线程时的开销。
进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。
视频播放器:下载视频同时播放视频。
多线程就是同一时间有多条代码语句同时执行。
“线程”与“进程”的联系与区别?
一般运行一个应用程序,就生成了一个进程, 这个进程拥有自己的内存空间,
这个进程还可以内部生成多个线程, 这些线程之间共用一个进程的内存空存空间,
所以线程之间共享内存是很容易做到的,多线程协作比多进程协作快一些,而且安全.
线程间通讯:
一个线程传递参数给另一个线程;一个线程执行完任务后转到另一个线程。方法如下:分线程回调
分线程回调主线程方法是什么,有什么作用?
[self performSelectorOnMainThread:@selector(buttonGo2) withObject:nil waitUntilDone:YES];
[self performSelector:@selector(buttonGo2) onThread:[NSThread mainThread] withObject:nil waitUntilDone:YES];
需要即时刷新ui控件的时候,经常使用。
线程池?
线程池是一堆项目的集合,就是一个线程队列来管理这些线程对象,如果需要处理一些任务,可以从线程池中直接取线程,而不是临时创建线程。比如NSOperationQueue就是一个线程池,管理NSOperation线程对象。
(单核CPU快速在多条线程之间切换)
同步、异步的主要区别
在于会不会阻塞当前线程,直到block中的任务执行完毕。
(是否开启新线程,以及根据串行并行来决定开启一条还是多条 )
同步任务优先级高,在线程中有执行顺序,不会开启新的线程。
异步任务优先级低,在线程中执行没有顺序,看cpu闲不闲。在主队列中不会开启新的线程,其他队列会开启新的线程。
同步:银行转账,数据库操作
异步:加载图片,然后主线程更新UI
队列:
是管理线程的,相当于线程池,能管理线程什么时候执行。
不管是串行队列(SerialQueue)还是并发队列(ConcurrencyQueue),都是FIFO队列。也就意味着,任务一定是一个一个地按照先进先出的顺序来执行。
串行队列:
任务会一个一个地执行,只有前一个任务执行完成,才会继续执行下一个任务。队列中的任务只会顺序执行(类似接力跑) 类似过收费站。
并发队列:
并发队列会尽可能多地创建线程去执行任务。并发队列中的任务会按入队的顺序执行任务,但是哪个任务先完成是不确定的。队列中的任务通常会并发执行(类似百米赛跑)
串行 并发的区别:
是否执行完一个再执行别的。
主队列:
每一个应用开发程序对应唯一一个主队列,直接get即可;在多线程开发中,使用主队列更新ui
全局队列:
是系统开发的,直接拿过来(get)用就可以;与并行队列类似,但调试时,无法确认操作所在队列
串行队列同步:操作不会新建线程、操作顺序执行
串行队列异步:操作需要一个子线程,会新建线程、线程的创建和回收不需要程序员参与,操作顺序执行,“最安全的选择”
并发队列同步:操作不会新建线程、操作顺序执行
并发队列异步:操作会新建多个线程(有多少任务,不见得就开n个线程执行)、操作无序执行;队列前如果有其他任务,会等待前面的任务完成之后再执行;场景:既不影响主线程,又不需要顺序执行的操作!
全局队列同步:操作不会新建线程、操作顺序执行
全局队列异步:操作会新建多个线程、操作无序执行,队列前如果有其他任务,会等待前面的任务完成之后再执行
主队列异步:操作都应该在主线程上顺序执行的,不存在异步的概念
主队列同步:如果把主线程中的操作看成一个大的block,那么除非主线程被用户杀掉,否则永远不会结束;主队列中添加的同步操作永远不会被执行,会死锁。
不同队列嵌套dispathch_sync(同步)任务的结果
// 1.全局队列,都在主线程上执行,不会死锁 dispatch_queue_priority_default
dispatch_queue_t q = dispatch_get_global_queue(dispatch_queue_priority_default, 0);
// 2.并行队列,都在主线程上执行,不会死锁 dispatch_queue_concurrent
dispatch_queue_t q = dispatch_queue_create("cn.itcast.gcddemo", dispatch_queue_concurrent);
// 3.串行队列,会死锁,但是会执行嵌套同步操作之前的代码 dispatch_queue_serial
dispatch_queue_t q = dispatch_queue_create("cn.itcast.gcddemo", dispatch_queue_serial);
// 4.主队列,直接死锁 dispatch_get_main_queue();
dispatch_queue_t q = dispatch_get_main_queue();
dispatch_async(q, ^{
NSLog(@"同步任务 %@", [NSThread currentThread]);
dispatch_sync(q, ^{
NSLog(@"同步任务 %@", [NSThread currentThread]);
});
});
•任务:执行什么操作
•队列:用来存放任务
主队列的任务虽然会加到主线程中执行,但是如果主线程里也有任务就必须等主线程任务执行完才轮到主队列的。
主线程队列中不能开启同步,会阻塞主线程。只能开启异步任务,开启异步任务也不会开启新的线程,只是降低异步任务的优先级,让cpu空闲的时候才去调用。而同步任务,会抢占主线程的资源,会造成死锁。
串行/并行针对队列 , 同步/异步针对任务
GCD 和 NSOperation、 NSThread简介:
•NSThread:
–优点:NSThread 比其他两个轻量级,使用简单
–缺点:需要自己管理线程的生命周期、线程同步、加锁、睡眠以及唤醒等。线程同步对数据的加锁会有一定的系统开销
•NSOperation:–不需要关心线程管理,数据同步的事情,可以把精力放在自己需要执行的操作上–NSOperation是面向对象的
•GCD:–Grand Central Dispatch是由苹果开发的一个多核编程的解决方案。
GCD 和 NSOperation比较:
- GCD的核心是C语言写的系统服务,执行和操作简单高效,因此NSOperation底层也通过GCD实现,换个说法就是NSOperation是对GCD更高层次的抽象,这是他们之间最本质的区别.因此如果希望自定义任务,建议使用NSOperation;
2.依赖关系,NSOperation可以设置两个NSOperation之间的依赖,第二个任务依赖于第一个任务完成执行,GCD无法设置依赖关系,不过可以通过dispatch_barrier_async来实现这种效果;
3.KVO(键值对观察),NSOperation和容易判断Operation当前的状态(是否执行,是否取消),对此GCD无法通过KVO进行判断;
4.优先级,NSOperation可以设置自身的优先级,但是优先级高的不一定先执行,GCD只能设置队列的优先级,无法在执行的block设置优先级;
5.继承,NSOperation是一个抽象类实际开发中常用的两个类是NSInvocationOperation和NSBlockOperation,同样我们可以自定义NSOperation,GCD执行任务可以自由组装,没有继承那么高的代码复用度;
6.效率,直接使用GCD效率确实会更高效,NSOperation会多一点开销,但是通过NSOperation可以获得依赖,优先级,继承,键值对观察这些优势,相对于多的那么一点开销确实很划算,鱼和熊掌不可得兼,取舍在于开发者自己;
7.取消任务:在NSOperationQueue中,我们可以随时取消已经设定要准备执行的任务。
http://www.cnblogs.com/xiangrikui/p/5283746.html
GCD的核心概念是将一个任务添加到队列,指定任务执行的方法,然后执行。 NSOperation则是直接将一个操作添加到队列中。
参考:
https://www.jianshu.com/p/9f2fc08f9947
http://www.tuicool.com/articles/YJJry2E
http://www.makaidong.com/博客园热/32954.shtml
http://www.cnblogs.com/dsxniubility/p/4296937.html
http://blog.csdn.net/c386890506/article/details/51171898
https://www.jianshu.com/p/266bec7c4dd2 //多线程面试题
https://www.jianshu.com/p/3d430c25dd65 //多线程面试题
面试问题:
为什么多线程用GCD/NSOperation而不用NSOperation/GCD呢?
NSOpertaionQueue用GCD构建封装的,是GCD的高级抽象, GCD更接近底层
GCD仅仅支持FIFO队列,而NSOperationQueue中的队列可以被重新设置优先级,调整顺序
GCD不支持异步操作之间的依赖关系设置。
NSOperationQueue支持KVO,意味着我们可以观察任务的执行状态。项目中一般在哪用到多线程?
多线程一般用于耗时操作,如:
网络请求
上传,下载文件
读取数据库
文件操作
大循环GCD除了开线程,还可以用在什么地方?
单例 (使用dispatch_once)
延迟执行 (使用dispatch_after,可以定义执行任务的线程)
定时器 (使用dispatch_source_set_event_handler)
快速迭代/循环遍历如何处理GCD造成的死锁问题
将队列改为非主队列
将调度方式改为异步调度分别下载2张图片后进行组合:
可以使用GCD的栅栏函数或者队列组,也可以使用NSOperation的依赖关系并行和并发的区别?
并发是指两个或多个事件在同一时间间隔内发生。
例如单CPU的处理多线程。
并行是指两个或者多个事件在同一时刻发生
例如多CPU的处理多线程。
串行(Sequential)、
并发(Concurrent)、
并行(parallel)
https://blog.csdn.net/qq_33290787/article/details/51790605
所写多线程可能被分配到一个CPU内核中执行,也可能被分配到不同CPU执行,分配过程是操作系统所为,不可人为控制。
排队打咖啡的例子
一皇二后是并发,二皇一后是并行。
双飞是并发,4P是并行。
GCD和NSOperation有什么区别?
GCD是纯C语言的API,NSOperation是基于GCD的OC版本封装
GCD只支持FIFO的队列,NSOperation可以很方便地调整执行顺序,设置最大并发数量
NSOperationQueue可以轻松在operation间设置依赖关系,而GCD需要些很多代码才能实现
NSOperationQueue支持KVO,可以检测operation是否正在执行(isExecuted),是否结束(isFinisn),是否取消(isCancel)
GCD的执行速度比NSOperation快
全局并发队列和使用create函数创建的并发队列主要区别
1.全局并发队列在整个应用程序中本身是默认存在的,并且有高级 默认 低级 后台四个优先级并发队列。而create函数创建的使我们自己实打实创建的
2.ios6.0前,GCD中使用create及retain的函数 最后都要一次release操作。而主队列 全局并发队列不需要我们手动release
3.栅栏函数只有在自己create的并发队列中使用 而不能与全局并发队列使用