在了解多线程以前,咱们须要先认识一下什么是 进程 和 线程。
**进程:**是在系统中运行的一个程序,每一个进程之间是独立的,每一个进程均运行在其专有且受保护的内存空间内。
**线程:**一个进程想要执行任务,必须得有线程(至少一个线程),线程是进程的基本执行单元,一个进程的全部任务都必须在线程中执行。
**线程的串行:**一个线程中任务的执行是串行的,若是要在一个线程中执行多个任务,只能一个一个的按顺序执行。
那么如何多个任务同时进行?这 便引出了咱们的多线程!ios
###1.基本概念
一个进程中能够开启多个线程,每一个线程能够并发/并行执行不一样的任务,多线程能够提交程序的执行效率。以下图(同时执行任务ABC):
编程
###2.多线程的原理 同一时间,CPU只能执行一个线程,只有一个线程正在执行,多线程并发执行,实际上是CPU快速的在多个线程之间切换。若是CPU的切换线程的时间足够快,就会形成多线程并发执行的假象。多线程
###3.多线程的优缺点
**优势: **(1)能适当的提升程序的执行效率
(2)能适当的提升资源的利用率(CPU,内存)
缺点:(1)开启线程会占用必定的内存空间(主线程1M,子线程0.5M),若是开启过多的线程会占用大量的内存空间,下降程序的性能。
(2)线程越多,CPU在调度线程上的开销就越大。 ###4.IOS中的多线程编程技术 IOS中有四种多线程的编程技术:并发
以上三种编程技术由上至下,抽象度层次是从低到高的,抽象度越高使用越简单,也是Apple最推荐使用的。框架
NSThread有二种建立方式异步
//实方法例 NSThread *thread = [[NSThread alloc]initWithTarget:self self selector:@selector(threadMethod ) object:nil]; [thread start]; //类方法 [NSThread detachNewThreadSelector: @selector (threadMethod ) toTarget:self withObject:nil];
参数解析:
selector :线程执行的方法,只能有一个参数,并且不能有返回值
target :selector消息发送的对象
argument:传输给target的惟一参数,也能够是nilasync
NSOperation的使用有两种方式:一种是使用定义好的两个类:NSInvocationOperation和NSBlockOperation,另外一种是继承NSOperation。函数
建立 NSInvocationOperation性能
//直接执行会在主线程中顺序执行 NSInvocationOperation * operation_1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run_A) object:nil]; [operation_1 start]; // 启动任务 // 建立一个队列,默认就是并行队列 NSOperationQueue *queue = [[NSOperationQueue alloc] init]; // 设置当前最大的执行数,能够控制是并行还串行,为1时就是串行 queue.maxConcurrentOperationCount = 1; // 将任务添加到队列中任务就自动执行了 [queue addOperation: operation_1];
建立NSBlockOperationspa
// 至少会有一个任务在主线程中执行,其余任务会被放到其余线程中执行 NSBlockOperation *blockOperation_1 = [NSBlockOperation blockOperationWithBlock:^{ [self run_A]; }]; [blockOperation_1 addExecutionBlock:^{ [self run_B]; }]; [opertion start];
###3.继承 NSOperation
#import <Foundation/Foundation.h> @interface CustomOperation :NSOperation @end #import"CustomOperation.h" -(void)main{ NSLog(@"%@",[NSTread currentThread]); }
##4、GCD GCD是Apple开发的一个多核编程的解决方法。该方法在MAC OS X10.6首次推出,随后引用到IOS4.0中。GCD是一个替代诸如:NSThread,NSOperationQueue,NSInvocationOperation等技术的很高效和强大的技术。
GCD队列:分为串行队列(DISPATCH_QUEUE_SERIAL)和并⾏队列(DISPATCH_QUEUE_CONCURRENT)。
** 系统提供的GCD队列:**
**主队列:**使用 dispatch_get_main_queue 函数来获取和主线程关联的串行队列
**全局队列:**系统提供的一个全局并行的队列,使用 dispatch_get_global_queue 函数获取
系统提供的dispatch方法:
//主线程执行一次 dispatch_async(dispatch_get_main_queue(), ^{ //task }); //后台执行 dispatch_async (dispatch_get_global_queue(0,0), ^{ //task }) //执行一次 static dispatch_once _t onceToken; dispatch_once(& onceToken,^{ //task }); //延迟执行 int sec = 2; dispatch_after(dispatch_time (DISPATCH_TIME_NOW , (int64_t) (sec * NSEC_PER_SEC)), dispatch_get_main_queue(),^{ //task })
###1.同步
同步任务:dispatch_sync,会阻塞后面的任务,必需当前任务完成后才能执行下一个
dispatch_sync(dispatch_get_main_queue(), ^{ self.imagView_1.image = [self downloadImage_one]; });
###2.异步
异步执行:dispatch_async,不会阻塞后面的任务,任务会立刻返回下一个任务不须要等待,当这个任务完成后会通知主线程.
dispatch_async(dispatch_get_main_queue(), ^{ [self run_D]; }); dispatch_async(dispatch_get_main_queue(), ^{ [self run_B]; }); dispatch_async(dispatch_get_main_queue(), ^{ [self run_C]; });
dispatch_get_main_queue() 获取主队列,主队列中的任务都会在主线程中执行, 是一个串行队列
###3.串行
自定义的串行队列,中异步执行任务,队列会把任务放到一个新的线程中按顺序执行
dispatch_queue_t serialQueue = dispatch_queue_create("串行队列", DISPATCH_QUEUE_SERIAL); dispatch_async(serialQueue, ^{ [self run_A]; }); dispatch_async(serialQueue, ^{ [self run_B]; }); dispatch_async(serialQueue, ^{ [self run_C]; }); */
###4.并行
dispatch_get_global_queue() 全局队列,是一个并行队列,能够将队列中的任务放到不一样的线程中执行
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ [self run_A]; }); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ [self run_B]; }); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [self run_C]; });
任务执行的优先级
DISPATCH_QUEUE_PRIORITY_HIGH 2 //最高 DISPATCH_QUEUE_PRIORITY_DEFAULT 0 //中等(默认) DISPATCH_QUEUE_PRIORITY_LOW (-2) //低 DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN //后台执行
若是在并行队列中同步执行任务,那么这些任务都会在主线程中按顺序执行,也就没有并发性了。
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [self run_A]; }); dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [self run_B]; }); dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [self run_C]; });
自定义的并行队列中异步执行任务,队列会把任务放到不一样的线程中执行
dispatch_queue_t concurrentlQueue = dispatch_queue_create("并行队列", DISPATCH_QUEUE_CONCURRENT); dispatch_sync(concurrentlQueue, ^{ [self run_A]; }); dispatch_sync(concurrentlQueue, ^{ [self run_B]; }); dispatch_sync(concurrentlQueue, ^{ [self run_C]; });
##5、NSOperation与GCD的区别 **一、底层实现:**GCD的底层是用C来实现的,NSOperation底层从ios4开始也是用的GCD来实现的。 **二、取消任务:**在NSOperationQueue中,咱们能够随时取消已经设定要准备执行的任务(固然,已经开始的任务就没法阻⽌了),而GCD无法中止已经加入queue的block(实际上是有的,但须要许多复杂的代码)。 ** 三、依赖关系:**NSOperation可以方便地设置依赖关系,咱们可让⼀个Operation依赖于另外一 个Operation,这样的话尽管两个Operation处于同一个并行队列中,但前者会直到后者执行完毕后再执⾏。 **四、监放任务的执行状况:**咱们能将KVO应用在NSOperation中,能够监听一个Operation是否完成或取消,这样子能比GCD更加有效地掌控咱们执行的后台任务。 **五、优先级:**在NSOperation中,咱们可以设置NSOperation的priority优先级,可以使同一个并行队列中的任务区分前后地执行,⽽在GCD中,咱们只能区分不一样任务队列的优先级,若是要区分block任务的优先级,也须要大量的复杂代码。 **六、代码复⽤:**咱们可以对NSOperation进行继承,在这之上添加成员变量与成员方法,提⾼整个代码的复⽤度,这比简单地将block任务排⼊入执⾏队列更有⾃由度,可以在其之上添加更多⾃定制的功能。