ios中得多线程技术主要使用3种:NSThreadNSOperationGCD

  一、NSThread: 最轻量级方法,但是不安全需要手动加锁,需要自己管理生命周期

    NSThread的使用方法有2种:   

// 第一种,需要start
1 NSThread *th1 = [[NSThread alloc] initWithTarget:self selector:@selector(btnClick) object:nil];
[th1 setName:@"线程1"];
[th1 start];
// 第二种
1 [NSThread detachNewThreadSelector:@selector(btnClick) toTarget:self withObject:nil];

  因为NSThread使用不安全,我们需要给它加锁(主要的实现代码):

 @property (nonatomic,assign) NSInteger fruits;
@property (nonatomic,strong) NSLock *lock;
- (void)viewDidLoad
{
[super viewDidLoad]; _lock = [[NSLock alloc] init];
_fruits = ;
} - (void)btnClick
{
@synchronized(_lock){ // 加锁 while (_fruits > ) { NSLog(@"当前线程为:%@ , 剩余票数为:%d",[NSThread currentThread], _fruits); _fruits--;
}
}
}

  二、GCD:(Grand Central Dispatch)是一种多核编码技术,用纯C语言编写。

  异步:具备开启线程的功能

  同步:不具备开启线程的功能

  并行队列:多个任务可以同时执行

  串行队列:执行完一个任务后再执行下一个任务

  下面来进行用代码说明:

 // 自定义异步方法
- (void)async:(dispatch_queue_t)queue
{
// 异步执行
dispatch_async(queue, ^{ NSLog(@"im1-%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{ NSLog(@"im2-%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{ NSLog(@"im3-%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{ NSLog(@"im4-%@",[NSThread currentThread]);
}); }
 // 自定义同步方法
- (void)sync:(dispatch_queue_t)queue
{
// 同步执行
dispatch_sync(queue, ^{ NSLog(@"im1-%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{ NSLog(@"im2-%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{ NSLog(@"im3-%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{ NSLog(@"im4-%@",[NSThread currentThread]);
}); }

调用异步执行方法

 // 创建一个全局并行队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, ); // 异步执行
[self async:queue];

最终的结果为:开启了四个线程,并且执行顺序是不定

 -- ::20.438 GCD[:1f07] im3-<NSThread: 0x7177ee0>{name = (null), num = }
-- ::20.432 GCD[:] im1-<NSThread: 0x7177d70>{name = (null), num = }
-- ::20.440 GCD[:] im4-<NSThread: 0x7178490>{name = (null), num = }
-- ::20.432 GCD[:1a03] im2-<NSThread: 0x75429f0>{name = (null), num = }
 // 创建一个全局串行队列
dispatch_queue_t queue = dispatch_queue_create("wys", NULL); // 异步执行
[self async:queue];

最终的结果为:开启了一个线程,执行顺序为从上往下依次执行

 -- ::19.415 GCD[:] im1-<NSThread: 0x71631a0>{name = (null), num = }
-- ::19.428 GCD[:] im2-<NSThread: 0x71631a0>{name = (null), num = }
-- ::19.437 GCD[:] im3-<NSThread: 0x71631a0>{name = (null), num = }
-- ::19.450 GCD[:] im4-<NSThread: 0x71631a0>{name = (null), num = }

调用主队列执行方法:

 // 创建主队列
dispatch_queue_t queue = dispatch_get_main_queue(); // 异步执行
[self async:queue];

最红的结果为:顺序执行并且不开启线程,在主线程中执行

 -- ::45.320 GCD[:c07] im1-<NSThread: 0x71560c0>{name = (null), num = }
-- ::45.333 GCD[:c07] im2-<NSThread: 0x71560c0>{name = (null), num = }
-- ::45.339 GCD[:c07] im3-<NSThread: 0x71560c0>{name = (null), num = }
-- ::45.347 GCD[:c07] im4-<NSThread: 0x71560c0>{name = (null), num = }
 // 创建主队列
dispatch_queue_t queue = dispatch_get_main_queue(); NSLog(@"start"); // 同步执行
[self sync:queue]; NSLog(@"end");

最终的结果为:执行到start就卡住了,不能往下执行

 -- ::12.856 GCD[:c07] start

调用同步执行方法:

 // 创建全局并行队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, ); // 同步执行
[self sync:queue];

最终的结果为:不开启线程,并且顺序执行,直接主线程执行

 -- ::27.448 GCD[:c07] im1-<NSThread: 0x71133c0>{name = (null), num = }
-- ::27.458 GCD[:c07] im2-<NSThread: 0x71133c0>{name = (null), num = }
-- ::27.468 GCD[:c07] im3-<NSThread: 0x71133c0>{name = (null), num = }
-- ::27.472 GCD[:c07] im4-<NSThread: 0x71133c0>{name = (null), num = }
 // 创建串行队列
dispatch_queue_t queue = dispatch_queue_create("wys", NULL); // 同步执行
[self sync:queue];

最终的结果为:不开启线程,并且顺序执行,直接主线程执行

 -- ::40.609 GCD[:c07] im1-<NSThread: 0x713e570>{name = (null), num = }
-- ::40.621 GCD[:c07] im2-<NSThread: 0x713e570>{name = (null), num = }
-- ::40.626 GCD[:c07] im3-<NSThread: 0x713e570>{name = (null), num = }
-- ::40.634 GCD[:c07] im4-<NSThread: 0x713e570>{name = (null), num = }

多线程之间的通信:UI界面的更新一定要在主线程中执行

 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, ), ^{ // 全局并行队列异步执行

         NSLog(@"全局并行队列异步执行 - %@",[NSThread currentThread]);

         // 获取网络图片数据
NSString *str = @"https://ss0.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=3384245408,2851245305&fm=21&gp=0.jpg";
NSURL *url = [NSURL URLWithString:str]; NSData *data = [NSData dataWithContentsOfURL:url]; UIImage *image = [UIImage imageWithData:data]; dispatch_async(dispatch_get_main_queue(), ^{ // 主线程异步执行 NSLog(@"主线程异步执行 - %@",[NSThread currentThread]); // 更新界面
[_im1 setImage:image];
}); });

最终的结果为:

-- ::08.513 GCD[:] 全局并行队列异步执行 -<NSThread: 0x754c530>{name = (null), num = }
-- ::10.657 GCD[:c07] 主线程异步执行 -<NSThread: 0x7132c80>{name = (null), num = }

利用多线程来实现延时执行:

1、利用GCD

 double delayInSeconds = 2.0; // 延时时长
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ // 在主线程中执行 NSLog(@"%@",[NSThread currentThread]); // 更新界面
[_im1 setImage:image]; });

2、利用此方法,performSelector为你要调用的方法,withObject为你要传得值,afterDelay为延时时长

 [self performSelector:@selector(downLoad) withObject:nil afterDelay:0.5f];

队列组:

 dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, ); dispatch_group_async(group, queue, ^{ // 代码1
}); dispatch_group_async(group, queue, ^{ // 代码2
}); dispatch_group_notify(group, queue, ^{ // 执行完代码1和代码2后,再执行此方法
});

  

  三、NSOperation:基于GCD,能控制最大并发线程数,主要有2个类:NSInvocationOperation和NSBlockOperation

  其步骤为: 创建队列、添加操作、将操作添加到队列

  A、NSInvocationOperation:

 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
NSOperationQueue *queue = [[NSOperationQueue alloc] init]; NSInvocationOperation *invo = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(buy) object:nil]; [queue addOperation:invo]; } - (void)buy
{
NSLog(@"%@",[NSThread currentThread]);
}

最后的结果为:开启了一个线程

 -- ::54.060 op1[:1e07] <NSThread: 0x71a6de0>{name = (null), num = }

  

  B、NSBlockOperation

 NSOperationQueue *queue = [[NSOperationQueue alloc] init];

     NSBlockOperation *b1 = [NSBlockOperation blockOperationWithBlock:^{

         NSLog(@"111--%@",[NSThread currentThread]);
}];
NSBlockOperation *b2 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"222--%@",[NSThread currentThread]);
}];
NSBlockOperation *b3 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"333--%@",[NSThread currentThread]);
}]; [queue addOperation:b1];
[queue addOperation:b2];
[queue addOperation:b3];

最后的结果为:开启了三个线程,自动异步执行

 -- ::59.897 op1[:1a03] --<NSThread: 0x7544fa0>{name = (null), num = }
-- ::59.901 op1[:] --<NSThread: 0x71506f0>{name = (null), num = }
-- ::59.902 op1[:] --<NSThread: 0x7545e60>{name = (null), num = }

设置依赖:

 // 设置依赖 ,b2依赖b1,b3依赖b2,所以执行顺序为,b1->b2->b3
[b2 addDependency:b1];
[b3 addDependency:b2];

设置队列的最大并发数量

 // 设置最大并发(最多同时并发执行3个任务)
queue.maxConcurrentOperationCount = ;

  C、主队列

 NSOperationQueue *queue = [[NSOperationQueue alloc] init];

     [queue addOperationWithBlock:^{

           NSLog(@"-------%@",[NSThread currentThread]);

                // 获取网络图片数据
NSString *str = @"https://ss0.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=3384245408,2851245305&fm=21&gp=0.jpg";
NSURL *url = [NSURL URLWithString:str]; NSData *data = [NSData dataWithContentsOfURL:url]; UIImage *image = [UIImage imageWithData:data]; [[NSOperationQueue mainQueue] addOperationWithBlock:^{ // 主队列 NSLog(@"******%@",[NSThread currentThread]); // 更新界面
[_im1 setImage:image];
}];
}];

最后的结果为:

 -- ::16.077 op1[:1c03] -------<NSThread: 0x71613e0>{name = (null), num = }
-- ::17.593 op1[:c07] ******<NSThread: 0x7134fa0>{name = (null), num = } // 主队列

iOS 多线程(NSThread、GCD、NSOperation)的更多相关文章

  1. iOS多线程 NSThread/GCD/NSOperationQueue

    无论是GCD,NSOperationQueue或是NSThread, 都没有线程安全 在需要同步的时候需要使用NSLock或者它的子类进行加锁同步 "] UTF8String], DISPA ...

  2. [iOS]多线程和GCD

    新博客wossoneri.com 进程和线程 进程 是指在系统中正在运行的一个应用程序. 每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内. 比如同时打开QQ.Xcode,系统就会分别 ...

  3. ios多线程NSThread

    1.简介: 1.1 iOS有三种多线程编程的技术,分别是: 1..NSThread 2.Cocoa NSOperation (iOS多线程编程之NSOperation和NSOperationQueue ...

  4. iOS 多线程学习笔记 —— NSOperation

    本文复制.参考自文章:iOS多线程编程之NSOperation和NSOperationQueue的使用 ,主要为了加强个人对知识的理解和记忆,不做他用.原作者声明: 著作权声明:本文由http://b ...

  5. 多线程 NSThread GCD

    ios多线程实现种类 NSThread NSOperationQueue NSObject GCD *************** 1.NSThread //线程 第一种 NSThread *thre ...

  6. iOS多线程开发之NSOperation - 快上车,没时间解释了!

    一.什么是NSOperation? NSOperation是苹果提供的一套多线程解决方案.实际上NSOperation是基于GCD更高一层的封装,但是比GCD更加的面向对象.代码可读性更高.可控性更强 ...

  7. iOS多线程开发之NSOperation

    一.什么是NSOperation? NSOperation是苹果提供的一套多线程解决方案.实际上NSOperation是基于GCD更高一层的封装,但是比GCD更加的面向对象.代码可读性更高.可控性更强 ...

  8. [转] iOS多线程编程之NSOperation和NSOperationQueue的使用

    <iOS多线程编程之NSThread的使用> 介绍三种多线程编程和NSThread的使用,这篇介绍NSOperation的使用. 使用 NSOperation的方式有两种, 一种是用定义好 ...

  9. iOS多线程编程之NSOperation和NSOperationQueue的使用

    前一篇 <iOS多线程编程之NSThread的使用> 介绍三种多线程编程和NSThread的使用,这篇介绍NSOperation的使用. 使用 NSOperation的方式有两种, 一种是 ...

  10. iOS多线程NSThread和GCD

    在iOS中啊  其实有多种方法实现多线程 这里只记录两个比较常用的  或者说我比较常用的 一个就是BSThread 另一个就是一听名字就比较霸气的妇孺皆知的GCD 先说一下NSThread吧 这个方式 ...

随机推荐

  1. eclipse对于虚拟内存的溢出处理

    第一个配置:-Xms1024m -Xmx2048m 第二个配置: 第二个配置:-XX:MaxPermSize=1024m 第三个配置就是eclipse安装包中的eclipse.ini文件 -Xms51 ...

  2. @Modifying 注解完成修改操作

    以上我们做的都是查询,那要如何实现 修改.删除和添加呢? 可以通过以下两种方式: (1)通过实现 CrudRepository 接口来完成(以后介绍): (2)通过 @Modifying 注解完成修改 ...

  3. DNS A记录 CNAME NS记录等的区别

    DNS域名解析 tracetrt dig A记录 将此域名绑定到固定ip C记录 将此域名绑定到另一个域名上,通常是A记录的别名 AAAA记录 用来绑定ipv6地址 https://www.ezloo ...

  4. PHP异步任务worker

    1.概述 异步任务框架主要包含两个角色: WorkerServer主要负责管理(启动,重启,监控等)worker工作进程. Worker负责从指定消息队列获取任务消息并执行任务. 为了提高worker ...

  5. Git把旧仓库的分支拉到新仓库中

    背景:项目新建了个git仓库(B仓库),放改版的新项目,现在运维所有项目构建都是在一个Jenkins里构建,然后拉镜像到相应服务器里,为了不让运维每次构建不同项目需要改git仓库地址,需要把原来项目仓 ...

  6. docker~aspnetcore2.0镜像安装软件的加速器

    一般对于安装软件加速时,我们大多数会选择阿里云,而对于aspnetcore2.0这个进项来说,由于使用的是Debian操作系统,所有我们要找到它对应的mirror列表,下面是我整理的一个sources ...

  7. CQRS之旅——旅程2(分解领域)

    旅程2:分解领域 设计停靠站点 "没有石头就没有拱门" --马可波罗 在本章中,我们将对Contoso会议管理系统进行一个高层次的概述.这将帮助您理解应用程序的结构.集成点以及应用 ...

  8. Vue.extend动态注册子组件

    写本篇文章之前其实也关注过vue中的一个关于加载动态组件is的API,最开始研究它只是用来实现一个tab切换的功能,使用起来也蛮不错的. is 预期:string | Object (组件的选项对象) ...

  9. EF增删查改加执行存储过程和sql语句,多种方法汇总

    ActionUrl c = new ActionUrl() { ActionName="test", RequestUrl="/123/123", SubTim ...

  10. 使用jQuery实现文本框input定位到文字最后(兼容所有浏览器)

    $.fn.setCursorPosition = function(position){ if(this.lengh == 0) return this; return $(this).setSele ...