iOS开发之多线程技术(NSThread、OperationQueue、GCD)
在前面的博客中如果用到了异步请求的话,也是用到的第三方的东西,没有正儿八经的用过iOS中多线程的东西。其实多线程的东西还是蛮重要的,如果对于之前学过操作系统的小伙伴来说,理解多线程的东西还是比较容易的,今天就做一个小的demo来详细的了解一下iOS中的多线程的东西。可能下面的东西会比较枯燥,但还是比较实用的。
多线程用的还是比较多的,废话少说了,下面的两张截图是今天我们实验的最终结果,应该是比较全的,小伙伴们由图来分析具体的功能吧:
功能说明:
1、点击同步请求图片,观察整个UI界面的变化,并点击测试按钮,红色是否会变成绿色。
2、NSThread按钮,是由NSThread方式创建线程并执行相应的操作。
3、Block操作按钮是用Block创建操作,并在操作队列中执行,下面的是Invocation操作
4、serial是GCD中的串行队列,concurrent是GCD中的并行队列
好啦,上面的咸蛋先到这儿,代码该走起啦。
一、准备阶段
1.不管使用代码写,还是storyboard或者xib等,先把上面所需的控件初始化好以便使用
2.点击测试UI按钮,改变下边label的颜色的代码如下:
//改变lable的颜色,在红绿颜色之间进行交换 - (IBAction)tapTestButton:(id)sender { static int i = 1; if (i == 1) { _testLabel.backgroundColor = [UIColor redColor]; i = 0; else _testLabel.backgroundColor = [UIColor greenColor]; i = 1; }
3.从网络上获取图片,并使用主线程显示进程调用情况
//从wanglu获取图片数据 -(NSData *) getImageData _count ++; int count = _count; //线程开始启动 NSString *str = [NSString stringWithFormat:@"%d.线程%@",count,[NSThread currentThread]]; NSLog(@"%@",str); NSData *data; [NSThread sleepForTimeInterval:0.5]; data = [NSData dataWithContentsOfURL:[NSURL URLWithString:IMAGEURL]]; NSString *str = [NSString stringWithFormat:@"%d.线程%@完毕",count,[NSThread currentThread]]; //请求数据的任务由其他线程解决,所以LogTextView的内容由主线程更新,也只有主线程才能更新UI [self performSelectorOnMainThread:@selector(updateTextViewWithString:) withObject:str waitUntilDone:YES]; return data; }
4.上面的用到了主线程来调用updateTextViewWithString方法,因为只有主线程才能更新UI,updateTextViewWithString:这个方法负责把线程的执行信息显示在View上,代码如下:
//在ViewController上显示图片请求情况 -(void)updateTextViewWithString:(NSString *)str NSString *old_str = [NSString stringWithFormat:@"%@\n%@",_logTextView.text, str]; _logTextView.text = old_str; //改变Label的颜色,便于观察 [self tapTestButton:nil]; }
5.把请求完的图片加载到ImageView上
//更新图片 -(void) updateImageWithData:(NSData *)data UIImage *image = [UIImage imageWithData:data]; [_testImage setImage:image]; }
6.加载图片的,也就是请求数据后在ImageView上显示
//由其他线程请求数据,由主线程来更新UI -(void)loadImageWithThreadName:(NSString *)threadName [[NSThread currentThread] setName:threadName]; NSData *data = [self getImageData]; [self performSelectorOnMainThread:@selector(updateImageWithData:) withObject:data waitUntilDone:YES]; }
二、通过各种方式来
1.同步请求图片测试,请求数据和更新UI都放在主线程中顺序执行,这样在请求数据的时候UI会卡死,代码如下;
1 //同步请求图片,视图阻塞的,因为主线程被占用,无法进行视图的更新 2 - (IBAction)tapButton:(id)sender { 3 NSData *data = [self getImageData]; 4 [self updateImageWithData:data]; 5 }
2.NSThread创建线程测试,用detachNewThreadSelector方法来创建新的线程会自动启动并执行,而不用调用start方法。代码如下:
//NSThread - (IBAction)tapButton2:(id)sender { //点击一次button就创建一个新的线程来请求图片数据 for (int i = 0;i i ++) { [NSThread detachNewThreadSelector:@selector(loadImageWithThreadName:) toTarget:self withObject:@"NSThread"]; }
3.NSInvocationOperation的使用,新建一个调用操作,然后添加到队列中执行,代码如下:
//NSInvocationOperation - (IBAction)tapInvocationOperation:(id)sender {
//实例化一个调用操作,来执行数据请求 NSInvocationOperation *invocationOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(loadImageWithThreadName:) object:@"Invocation"]; //把上面的调用操作放到操作队列里,队列会自动开启一个线程调用我们指定的方法 [operationQueue addOperation:invocationOperation]; }
4.block的操作,新建一个block操作,并添加到队列中执行,代码如下:
//BlockOperation - (IBAction)tapBlockOperation:(id)sender { __weak __block ViewController *copy_self = self; //创建BlockOperation NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{ [copy_self loadImageWithThreadName:@"Block"]; //添加到操作队列 NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init]; [operationQueue addOperation:blockOperation]; for (int i = 0;i i ++) { //另一种方式 [operationQueue addOperationWithBlock:^{ [copy_self loadImageWithThreadName:@"Block"]; }
5.GCD中的串行队列:
//串行队列 - (IBAction)tapGCDserialQueue:(id)sender { //创建串行队列 dispatch_queue_t serialQueue = dispatch_queue_create("mySerialQueue", DISPATCH_QUEUE_SERIAL);
//创建并行队列 dispatch_queue_t concurrentQueue = dispatch_queue_create("myConcurrentQueue", DISPATCH_QUEUE_CONCURRENT); __weak __block ViewController *copy_self = self; for (int i = 0;i i ++) { //异步执行队列 dispatch_async(concurrentQueue, ^{ [copy_self loadImageWithThreadName:@"Concurrent"]; }
以上是各个按钮对应的方法,下面的截图是执行结果:
三、线程间的同步问题(为我们的线程添加上同步锁)
在操作系统中讲多线程时有一个名词叫脏数据,就是多个线程操作同一块资源造成的,下面就修改一下代码,让数据出现问题,然后用同步锁来解决这个问题
1.在getImageData方法(标题一中的第3个方法)中有两条语句。这个用来显示线程的标号。上面的标号是没有重复的。
1 _count ++; 2 int count = _count;
在两条语句中间加一个延迟,如下:
_count ++; [NSThread sleepForTimeInterval:1]; int count = _count;
如果运行的话,会有好多标号是重复的,如图一,__count是成员变量,多个线程对此他进行操作,所以会出现标号不一致的情况,下面我们加上同步锁
(1)用NSLock加同步锁,代码如下:
//通过NSLock加锁 [_lock lock]; _count ++; [NSThread sleepForTimeInterval:1]; int count = _count; [_lock unlock];
(2)通过@synchronized加同步锁,代码如下:
//通过synchronized加锁 int count; @synchronized(self){ _count ++; [NSThread sleepForTimeInterval:1]; count = _count; }
加锁前后的运行效果如下:
GCD的串行队列开始执行的顺序如下,下面是是在一个线程中按FIFO的顺序执行的:
GCD中的并行队列,是在不同的线程中同时执行的:
[ios开发]-APP-上架流程 由于苹果的机制,在非越狱机器上安装必须通过官方的Appstore, 开发者开发好应用后上传Appstore,也需要通过审核等环节。 AppCan作为一个跨主流平台的一个开发平台,也对ipa包上传Appstore作了支持。 本文从三个流程来介绍如何实现AppCan在 线编译出ipa包,以及上传到苹果Appstore。
相关文章
- iOS的高德地图标注特定位置
- 从零开始学 iOS 开发的15条建议「建议收藏」
- Uni开发的app,使用Windows S10,放在ios上,全程跟着一个马平川。
- linux查看iostat_ios命令行怎么打开
- iOS锁屏时钟_ios时钟怎么调
- IOS内测记录:在自有App中运行小程序游戏
- AnyMP4 iOS Cleaner for mac(IOS文件清理工具)v1.0.16激活版
- iOS 多线程:『GCD』详尽总结(一)
- 【iOS 开发】iOS 开发 简介 (IOS项目文件 | MVC 模式 | 事件响应机制 | Storyboard 控制界面 | 代码控制界面 | Retina 屏幕图片适配)
- IOS – OpenGL ES 图像晕影移动 GPUImageVignetteFilter
- iOS多线程到底不安全在哪里详解手机开发
- iOS开发中GCD在多线程方面的理解详解手机开发
- iOS 图片压缩 和等比压缩 指定缩放比例压缩详解手机开发
- iOS监听电话铃声响起,挂断的方法详解手机开发
- ios基础:iOS改变状态栏字体颜色详解手机开发
- 探索Linux系统:在iOS上下载(linux系统ios下载)
- 在iOS上搭建MySQL数据库连接(ios连接mysql数据库)
- appLinux开发探索之路:从iOS APP开始(linux开发ios)
- Linux下开发iOS应用:挑战还是机会?(linux做ios开发)
- MacOS 与 iOS:由浅入深的连接(macos和ios)
- Linux技术可以开发IOS系统?(linux能开发ios吗)
- iOS与Linux:新老技术的融合(ios与linux的关系)
- 微软更新iOS版微软远程桌面应用(RDP) 带来诸多新功能和优化改进等
- 苹果公布iOS 15系列机型支持列表 iPhone 6S/6SP/初代SE依然可以升级
- 平台开发iOS开发:基于Linux平台的世界(ios基于linux)
- 开启一个崭新世界:Linux与iOS系统(linux系统ios)
- IOS上可以安装Oracle吗(ios能装oracle吗)
- 移动端iOS技术实现Oracle数据库连接(ios联接oracle)
- iOS让Oracle无处不在(ios支持oracle么)