iOS开发中多线程的应用

xiaoxiao2021-02-27  151

         1.相关概念

       线程:是CPU执行任务的最小单位,同一线程内的任务是串行执行的。

       主线程:程序启动时创建的一条线程,并且在执行,该线程叫做主线程,主线程是UI线程,负责刷新UI。

       进程:可以理解为一个运行中的应用程序,是系统进行资源分配的最小单位。每个进程之间是相互独立的。

       多线程:即在一个进程中开启了多条线程执行任务。 

       串行执行:串行执行是指在同一条线程中的任务,是按顺序执行的。

       多线程并行(并发)执行:每条线程同时执行任务。但是在同一时间内,CPU在一个时间内只能执行一个线程,多线程并行执行,是由于CPU在各个线程之间快速的来回切换,造成了各个线程同时在运行的假象。

       2.iOS开发中的多线程技术

       (1)pthread:在iOS开发中几乎不会用到,暂且不做介绍;

       (2)NSThread:偶尔使用,在本文中只用作获取当前线程,即[NSThread currentThread];

       (3)GCD:在iOS开发中经常使用,能够自动充分的利用设备的多核特性;

       (4)NSOperation:基于GCD,比GCD多了一点简单使用的功能。

       3.GCD在iOS开发中的基本使用

       a.创建队列;

       b.在队列中添加任务;

       c.选择执行函数(同步或者异步)。

       GCD有一下几种组合:

       (1)同步函数+串行队列:不会开启新线程,任务在线程中串行执行。

// 同步函数+串行队列 // 不会开新线程,串行执行 - (void)syncSerial { // 创建队列 // 第一个参数是C语言字符串,第二个参数是队列类型 //DISPATCH_QUEUE_CONCURRENT:并发队列 //DISPATCH_QUEUE_SERIAL:串行队列 dispatch_queue_t queue = dispatch_queue_create("com.SZU", DISPATCH_QUEUE_SERIAL); // 同步函数,第一个参数是创建的队列,第二个参数是需要执行的任务 dispatch_sync(queue, ^{ NSLog(@"1----%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"2----%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"3----%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"4----%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"5----%@",[NSThread currentThread]); }); }        (2)同步函数+并行队列:不会开启新线程,任务串行执行 // 同步函数+并行队列 // 不会开新线程,串行执行 - (void)syncConcurrent { // 创建队列 dispatch_queue_t queue = dispatch_queue_create("com.SZU", DISPATCH_QUEUE_CONCURRENT); // 并行队列的另外一种创建方式,全局并行队列,第一个参数为队列的优先级,第二个参数为备用项。 // #define DISPATCH_QUEUE_PRIORITY_HIGH 2 // #define DISPATCH_QUEUE_PRIORITY_DEFAULT 0 // #define DISPATCH_QUEUE_PRIORITY_LOW (-2) // #define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN // dispatch_queue_t queue1 = dispatch_get_global_queue(0, 0); // 同步函数,第一个参数是创建的队列,第二个参数是需要执行的任务 dispatch_sync(queue, ^{ NSLog(@"1----%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"2----%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"3----%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"4----%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"5----%@",[NSThread currentThread]); }); }        (3)异步函数+串行队列:开启一条新线程,任务串行执行

// 异步函数+串行队列 // 开一条新线程,串行执行 - (void)asyncSerial { // 创建队列 dispatch_queue_t queue = dispatch_queue_create("com.SZU", DISPATCH_QUEUE_SERIAL); dispatch_async(queue, ^{ NSLog(@"1----%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"2----%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"3----%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"4----%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"5----%@",[NSThread currentThread]); }); }        (4)异步函数+并行队列:开启多条线程,任务并行执行

// 异步函数+并行队列 // 开启新线程,并行执行 - (void)asyncConcurrent { // 创建队列 dispatch_queue_t queue = dispatch_queue_create("com.SZU", DISPATCH_QUEUE_CONCURRENT); // 添加任务 dispatch_async(queue, ^{ NSLog(@"1----%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"2----%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"3----%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"4----%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"5----%@",[NSThread currentThread]); }); }        (5)GCD中有一种特殊的队列,叫做主队列,主队列是一种特殊的串行队列,是在主线程中执行的。

       

// 同步函数+主队列(会发生死锁) - (void)syncMain { // 主队列是特殊的串行队列,主队列中的任务在主线程中执行。主线程是UI线程,所有UI刷新的操作都在主线程中完成 NSLog(@"来到了这里"); dispatch_queue_t queue = dispatch_get_main_queue(); dispatch_sync(queue, ^{ NSLog(@"1----%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"2----%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"3----%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"4----%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"5----%@",[NSThread currentThread]); }); } // 异步函数+主队列 // 任务会在主线程中执行 - (void)asyncMain { dispatch_queue_t queue = dispatch_get_main_queue(); dispatch_async(queue, ^{ NSLog(@"1----%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"2----%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"3----%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"4----%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"5----%@",[NSThread currentThread]); }); }        (6)GCD的其他用法

/* GCD的用法拓展 */ // 栅栏函数,保证栅栏函数前面的任务执行完之后再执行下面的任务 - (void)barrier { dispatch_queue_t queue = dispatch_queue_create("com.SZU", DISPATCH_QUEUE_CONCURRENT); dispatch_async(queue, ^{ NSLog(@"1----%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"2----%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"3----%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"4----%@",[NSThread currentThread]); }); dispatch_barrier_async(queue, ^{ NSLog(@"栅栏函数"); });// 执行完前面的任务之后,在执行下面的任务 dispatch_async(queue, ^{ NSLog(@"5----%@",[NSThread currentThread]); }); } // 延迟执行 - (void)delay { NSDate *date = [NSDate date]; NSLog(@"%@",date); dispatch_queue_t queue = dispatch_queue_create("com.SZU", DISPATCH_QUEUE_SERIAL); // 第一个参数为延迟时间 // 第二个参数的队列可以更换 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), queue, ^{ NSDate *date1 = [NSDate date]; NSLog(@"%@",date1); NSLog(@"延迟执行--%@",[NSThread currentThread]); }); } // 一次性代码 - (void)once { for (NSInteger i = 0; i < 5; i++) { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ NSLog(@"一次性代码"); }); NSLog(@"%ld",i); } } // 队列组 - (void)queueGroup { // 创建队列组 dispatch_group_t group = dispatch_group_create(); // 创建队列 dispatch_queue_t queue = dispatch_queue_create("com.SZU", DISPATCH_QUEUE_CONCURRENT); // 添加任务 dispatch_group_async(group, queue, ^{ // 下载图片1 NSURL *url = [NSURL URLWithString:@"http://www.huabian.com/uploadfile/2015/0914/20150914014032274.jpg"]; NSData *data = [NSData dataWithContentsOfURL:url]; self.image1 = [UIImage imageWithData:data]; }); dispatch_group_async(group, queue, ^{ // 下载图片2 NSURL *url = [NSURL URLWithString:@"http://www.huabian.com/uploadfile/2015/0914/20150914014032274.jpg"]; NSData *data = [NSData dataWithContentsOfURL:url]; self.image2 = [UIImage imageWithData:data]; }); // 队列组中的任务完成之后执行下面的代码,合成图片 dispatch_group_notify(group, queue, ^{ // 开启图形上下文 UIGraphicsBeginImageContext(CGSizeMake(300, 300)); // 画图 [self.image1 drawInRect:CGRectMake(0, 0, 300, 150)]; [self.image2 drawInRect:CGRectMake(0, 150, 300, 150)]; // 根据画的图,拿到image UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); // 关闭图形上下文 UIGraphicsEndImageContext(); // 在主线程中刷新UI,主线程是UI线程 // 方法1 [self performSelector:@selector(showImage:) onThread:[NSThread mainThread] withObject:image waitUntilDone:YES]; // 方法2 // [self performSelectorOnMainThread:@selector(showImage:) withObject:image waitUntilDone:YES]; }); } - (void)showImage:(UIImage *)image { self.imageView.image = image; }        4.NSOperation的应用

/* NSOperation */ // NSOperation执行任务是否开启线程,开启几条线程由系统决定 // NSBlockOperation - (void)blockOperation { // 不使用NSOperationQueue,创建NSBlockOperation对象并添加任务 NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"1----%@",[NSThread currentThread]); }]; // 添加新任务 [op addExecutionBlock:^{ NSLog(@"2----%@",[NSThread currentThread]); }]; [op addExecutionBlock:^{ NSLog(@"3----%@",[NSThread currentThread]); }]; [op addExecutionBlock:^{ NSLog(@"4----%@",[NSThread currentThread]); }]; [op addExecutionBlock:^{ NSLog(@"5----%@",[NSThread currentThread]); }]; // 调用start方法 [op start]; } // NSInvocationOperation - (void)invocationOperation { NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(operation1) object:nil]; NSInvocationOperation *op2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(operation2) object:nil]; NSInvocationOperation *op3 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(operation3) object:nil]; NSInvocationOperation *op4 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(operation4) object:nil]; NSInvocationOperation *op5 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(operation5) object:nil]; [op1 start]; [op2 start]; [op3 start]; [op4 start]; [op5 start]; } - (void)operation1 { NSLog(@"1----%@",[NSThread currentThread]); } - (void)operation2 { NSLog(@"2----%@",[NSThread currentThread]); } - (void)operation3 { NSLog(@"3----%@",[NSThread currentThread]); } - (void)operation4 { NSLog(@"4----%@",[NSThread currentThread]); } - (void)operation5 { NSLog(@"5----%@",[NSThread currentThread]); } // 自定义NSOperation - (void)customOperation { // 自定义NSOperation需要重写main方法 PGXOperation *op = [[PGXOperation alloc] init]; [op start]; } // NSOperation配合NSOperationQueue使用 - (void)operationQueue { // 1.创建队列 // 使用init方法创建的队列为非主队列,同时具备串行以及并行的操作 NSOperationQueue *queue = [[NSOperationQueue alloc] init]; // 2.封装任务 NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"1----%@",[NSThread currentThread]); }]; [op1 addExecutionBlock:^{ NSLog(@"2----%@", [NSThread currentThread]); }]; NSInvocationOperation *op2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(operation3) object:nil]; // 添加依赖项,即op2完成之后才能进行op1 [op1 addDependency:op2]; // 3.添加任务到队列中 [queue addOperation:op1]; [queue addOperation:op2]; [queue addOperationWithBlock:^{ NSLog(@"4----%@",[NSThread currentThread]); }]; } // NSOperation的其他主要用法 - (void)other { NSOperationQueue *queue = [[NSOperationQueue alloc] init]; // suspended属性用于暂队列中的任务,设置YES时,暂停任务,任务暂停时,若当前任务还未完成,则在完成该任务之后暂停 queue.suspended = YES; // 取消队列中的所有任务 [queue cancelAllOperations]; }         https://github.com/SevenDK/multiThread  这是多线程完整的代码地址。

       

转载请注明原文地址: https://www.6miu.com/read-13158.html

最新回复(0)