多线程
NSThread : 轻量级的方式(具有很少的规则和惯例,依赖的东西少),完全面向对象的,可以直接操控对象,但是,它的声明周期需要我们手动管理。
[NSThread cuttentThread]
可以获取到当前线程类,就可以知道当前线程的各种属性,用于调试很方便。
优点 : 比其他两个轻量级,使用起来最直观.
缺点 : 需要我们手动管理生命周期、线程同步;线程总数无法控制(每次创建并不能重用之前的线程,只能创建一个新的线程).GCD : 它会自动管理生命周期(创建线程、调度任务、销毁线程)。在GCD中加入了两个概念:任务和队列。
任务 : 有两种执行方式:同步执行和异步执行。主要区别在于会不会阻塞当前线程,直到block中的任务执行完毕。
队列:用于存放任务。有两种队列:串行队列和并行队列。放到串行队列里的任务,GCD会FIFO地取出来一个,执行一个,这样一个一个的执行;放到并行队列的任务,GCD也会FIFO的取出来,但是取出来一个就会放到别的线程里,然后再取出来一个又放到另一个线程里。由于取的动作很快忽略不计,看起来所有的任务都是一起执行的。GCD会根据系统资源控制并行的数量。
对列组 :可以将很多队列添加到一个组里,当这个组里所有的任务都执行完了,队列会通过一个方法通知我们。
dispatch_group_t
。dispatch_queue_t queue = dispatch_get_global_queue(DEFAULT_QUEUE_PRIORITY_DEFAULT, 0); dispatch_group_t group = dispatch_group_create(); dispatch_group_async(group, queue, ^{ //下载图片 }); dispatch_group_async(group, queue, ^{ //下载图片 }); dispatch_group_notify(group, dispatch_get_main_queue(), ^{ //合并图片 });
优点:自动管理生命周期(创建线程、调度任务、销毁线程);会自动根据任务在多核处理器上分配资源优化程序(对于多核运算更加有效)。使用起来最简单。性能更好。
GCD队列分为三种:
主队列:主线程就在这个队列中,是个串行队列;
全局并发队列:是个并行队列,有高、默认、低和后台4个优先级;
用户队列:是用函数dispatch_queue_create
创建的自定义队列;注意:
在主线程中,不能使用主线程队列的同步调用,这样就会发生死锁,互相等待完成。例如:- (void)viewDidLoad { [super viewDidLoad]; NSLog(@"=================4"); dispatch_sync(dispatch_get_main_queue(), ^{ NSLog(@"=================5"); }); NSLog(@"=================6"); } // 结果只会打印4,5和6都不会打印 sync函数等待主线程执行完成再执行block里的内容,主线程等待sync函数返回,去执行后面的内容。
NSOperation和NSOperationQueue
1 . NSoperation是苹果公司对GCD的封装,完全面向对象。可以看到NSOperation和NSOperationqueue分别对应任务和队列。 将要执行的任务封装到一个NSOperation对象中; 将次任务添加到一个NSOperationQueue对象中。2 . NSOperation是一个抽象类,所以不能封装任务,但它有2个子类用于封装任务。分别是NSInvocationOperation和NSblockOperation。创建一个operation后,需要调用
start
方法来启动任务,它会默认在当前队列同步执行。但是NSBlockOperation还有一个方法:addExecutionBlock:
,通过这个方法可以给Operation添加多个执行Block。这样Operation中的任务会并发执行,它会在主线程和其他的多个线程执行这些任务。注意:addExecutionBlock
方法必须在srart()
方法之前执行,否则就会报错。3 . 自定义Operation:自定义Operation需要继承NSOperation类,并实现其
main()
方法。4 . NSOperationQueue:按类型来说有两种类型:主队列和其他队列。只要添加到队列,会自动调用任务的
srart()
方法。5 . NSOperation有一个非常实用的功能,那就是添加依赖。比如有3个任务,A:从服务器上下载一张图片,B:给这张图片加个水印,C:把图片返回给服务器。这时就用到依赖了:任务二依赖任务一,任务三依赖任务二。注意:不能添加相互依赖。
6 . 优点:不需要关心线程管理、数据同步的事情
NSOperation和GCD比较的优点:
GCD使用的API是C语言的, 抽象成NSOperation和NSOperationQueue之后,代码风格统一了,不用在面向对象的OC中写面向过程的C语言代码了。
GCD不能给操作设置依赖关系以及取消操作。这些功能都已经封装到NSOperation对象里面了。
NSOperation可以设置并发操作数量。如果任务之间有依赖关系或者想要监听任务完成状态的情况下优先选择NSOperation否则使用GCD,因为苹果专门为GCD做了性能上面的优化。
在NSOperation中,我们能够设置NSOperation的priority优先级,能够使同一个并行队列中的任务区分先后地执行,而在GCD中,我们只能区分不同任务队列的优先级,如果要区分block任务的优先级,也需要大量的复杂代码.
什么时候用多线程
处理需要耗时的方法,比如请求数据,图片等,对比较耗时的操作通过开启一个后台线程来处理,不阻塞主线程(卡UI)。
进程
进程指在系统中正在运行的一个应用程序(或开辟的一块空间),每个线程之间是独立的,进程是不做任务的,只有开辟了线程才能做任务的。例如:我们电脑同时打开网易云音乐和Xcode,那么系统就会分别启动两个进程。
一个进程要想执行任务,必须要有线程(每一个进程至少要有一个 线程);线程是进程的基本执行单元,一个进程的所有任务都在线程中执行。进程之间不能共享资源,但是线程之间可以共享资源。
线程同步和异步分别是什么意思?如何实现线程的同步?
线程同步是多个线程同时访问同一资源,等待资源访问结束,浪费时间,效率低。
线程异步是访问资源时在空闲等待时同时访问其他资源,实现多线程机制。
通过添加线程锁实现线程的同步。单线程不加锁可以,但是多线程的时候,对于公共资源必须加锁。当线程并发也就是异步访问,就会出现问题。所以要把异步的变成同步的才行。
如何实现多线程按顺序执行?
在NSOperationQueue,可以通过添加依赖完成线程的顺序执行。
在GCD有group线程组,但是group里的任务是异步执行的。