iOS开发-------多线程编程
来源:互联网 发布:seo专业优化公司 编辑:程序博客网 时间:2024/05/03 14:15
在大学里接触了一部分编程语言,如C++,Java,C#,虽然学的不是很好,但是每每提到多线程,总会感觉很高大上,毕竟学语言的一开始都不会接触到这一部分。
需要明白的是,每一个程序不是一个线程,而是一个进程,CPU将时间片分配给进程,然后是进程在将时间片分给自己的线程,也就是说一个系统有多个进程,一个进程又有多个线程。
学过的操作系统说过,所谓的多线程,实际就是CPU在处理各种事务的时候分成了时间片,时间片的间隔时机极短,就是说人根本感觉不出来,所以会认为是多线程,也就是并发操作。实际还是按照系统内部的非分配方法来操作的。
为什么要使用多线程呢,比如当某个任务需要长时间运行,但是如果只是单线程,那么后面的程序就要等到它执行完毕之后才可以运行,这样就浪费了很多的事件,也会造成用户体验的不爽。
Objective-C中的多线程,一般讲的时候都是分3类,楼主学的时候也是,但是学完之后会觉得还是GCD比较好用,现在看来比较高大上,通过一个简单的小例子来看,会简单去多,那么依旧采用之前的风格,通过实例来说明东西。
例子就是说,通过点击一个按钮,将进度条动态的前进。为了方便演示(demonstrate),楼主用stroyboard来布局。
NSThread(线程类)
通过名字来看,直接了当,就是一个线程的类,那么首先来了解一下NSThread的基本用法
/** * 创建一个线程,是一个目标动作回调的方法 * * @param object 表示需要传入的参数是什么,一般指线程的名字 */ NSThread * thread = [[NSThread alloc]initWithTarget:self selector:@selector(test1) object:nil]; //越高表示cpu的时间优先分配,0 ~ 1,并不是说越高就立马执行 thread.threadPriority = 1; //线程休眠时间为1秒,表示让出主线程队列的位置,休眠结束后,继续在主线程的队列排队 [NSThread sleepForTimeInterval:1]; //进入就绪队列,但不代表能够立即执行,需要在线程队列中排队 [thread start];
首先在button的点击方法中创建一个线程
//start按钮被点击时- (IBAction)startButtonClick:(id)sender{ //创建一个线程 NSThread * thread1 = [[NSThread alloc]initWithTarget:self selector:@selector(threadFun) object:nil]; //添加到就绪队列 [thread1 start];}
接下来完成线程的回调方法
//子线程执行的方法-(void)threadFun{ for (NSInteger i = 0; i <= 100; i++) { //休眠0.01秒 [NSThread sleepForTimeInterval:0.02]; [self updateProgress]; }}
更新进度条的方法如下
//progress更新的办法-(void)updateProgress{ self.progressView.progress += 0.01;}
那么看一下结果吧,是不是想象的那么样呢
结果恐怕不是之前想的那样,这样子是在2秒后突然进度条就满了,原因呢:
1、progressView是在主线程中创建的,所以子线程没有权利修改,即使有的时候可以改,但是一般是错误的。
2、在子线程中执行的方法,那么这个方法就是子线程的。
3、最本质的原因,就是在runloop中,当按钮点击了之后,他的首响应是button,无暇顾及progress进度,只有当button的回调方法结束后,才可以管progressView,但是那个时候progress早已经运行完了,所以2秒后突然进度条满了。
怎么修改呢,只需要子线程执行的方法中改一句话即可
//子线程执行的方法-(void)threadFun{ for (NSInteger i = 0; i <= 100; i++) { //休眠0.01秒 [NSThread sleepForTimeInterval:0.02]; //在主线程执行该方法 [self performSelectorOnMainThread:@selector(updateProgress) withObject:nil waitUntilDone:NO];//waitUntilDone 表示下面如果还有语句的话,为YES表示必须执行完这个方法之后才能运行下面的语句 }}
这样用NSThread就完成了。
NSOperation(操作类)
NSOperation(操作类)楼主感觉比较麻烦,但是又不能不知道,所以也按照自己的理解来描述一下,如果不对,也请及时告诉我,不要继续误导其他人
首先用到这个类,要写一个类继承于NSOoeration,并且要重写它的 main( ) 方法,这个方法不同于C语言的main方法,它仅仅是一个方法的名字,只不过当operation执行的时候会自动的调用这个main方法。
然后就是有的特点和NSThread有点相似,都是将进程或者操作放入系统的队列中进行排队,比如下面是button点击时候的回调方法
//start按钮点击的回调- (IBAction)buttonPressed:(id)sender{ //判断是否已经存在 if (!self.operation) { //创建一个operation操作类 self.operation = [[MyOperation alloc]init]; } //创建一个操作队列 NSOperationQueue * queue = [[NSOperationQueue alloc]init]; //如果没有完成这个操作,也就是说一旦开始,就不能将进程杀死,就要等他执行完毕才可 if ([self.operation isFinished] == NO) { //将操作放入操作队列 [queue addOperation:self.operation];//运行的时候自动调用MyOperation的main方法,必须是main方法 } }
因为之前也提到过,子线程中是不能够改变主线程创建的组件的属性的,那么如何在子线程中告诉主线程呢,首先就想到了回调,但是楼主技术不达标,所以最熟悉的Block回调不能解决相关问题,所以选择了委托回调的方式。
委托模式必须要有协议,那么协议如下
@protocol MyOperationDelegate <NSObject>@optional/** * 回调返回的进度增量 * * @param myOperation 当前的操作类对象 * @param i 进度条的增量 */-(void)myOperation:(MyOperation *)myOperation updateProess:(CGFloat)i;@end
接着就开始继承于NSOperation(操作类)的自定义类MyOperation
//// MyOperation.h// 多线程 NSOperation//// Created by YueWen on 15/10/1.// Copyright (c) 2015年 YueWen. All rights reserved.//#import <Foundation/Foundation.h>#import <UIKit/UIKit.h>@protocol MyOperationDelegate;@interface MyOperation : NSOperation//履行协议的归零弱引用的代理对象@property(nonatomic,weak)id<MyOperationDelegate> delegate;@end
因为说过用NSOperation,要重写main()方法,重写如下
-(void)main{ for (NSInteger i = 0; i <= 100; i++) { //休眠0.02秒 [NSThread sleepForTimeInterval:0.02]; //判断代理是否有这个方法 if ([self.delegate respondsToSelector:@selector(myOperation:updateProess:)]) { //用主线程执行代理的委托方法 [self performSelectorOnMainThread:@selector(updateProessd) withObject:nil waitUntilDone:NO]; } }}
-(void)updateProessd{ [self.delegate myOperation:self updateProess:0.01];}
最后是viewController了,不要忘记设置代理啊,楼主表示经常忘,导致没有相关的效果
//设置代理self.operation.delegate = self;
#pragma mark - MyOperation Delegate//履行协议方法-(void)myOperation:(MyOperation *)myOperation updateProess:(CGFloat)i{ self.progressView.progress += i;}
来看看效果图吧
GCD (Grand Gentral Dispatch 中央处理)
上面的两种方法,第一种NSThread类,好理解,但是感觉不是高大上,第二种NSOperation类,有感觉繁琐,因为用到了回调,那有没有一种代码简介又显得高大上的方法呢,自然是有的,就是这里说的GCD(又中央来对线程进行派发处理)
第一看会觉得很麻烦,因为出现了许多的‘_’,所以会有这种感觉,首先分开了解一下
//首先获得一个派发队列,queue即为获得的派发队列,是个单例,后面的参数...(楼主表示不懂,但是都是这么写的0.0),是一个C语言类型,不带*dispatch_queue_attr_t queue = dispatch_get_global_queue(0, 0);
//在派发队列上放置一个子线程的异步操作dispatch_async(myQueue, ^{ NSLog(@"我是子线程的异步操作"); });
如何获得主线程,来进行操作呢,毕竟progressView的修改是在主线程中进行修改的
//获得主线程dispatch_async(dispatch_get_main_queue(), ^{ //主线程的操作 NSLog(@"我是主线程的操作"); });
dispatch_async(dispatch_queue_t queue, ^(void)block);//表示不需要等待上面的代码执行完毕 dispatch_sync(dispatch_queue_t queue, ^(void)block);//表示必须等待上面的代码执行完毕才可执行,有点同步的意思,区别就和方法中的waitUntilDo相似
//按钮点击时的回调方法- (IBAction)startButtonClick:(id)sender{ [self updateProgress];}
接着是按钮点击后执行的方法
//更新进程-(void)updateProgress{ //首先获得一个派发队列,queue即为获得的派发队列,是个单例,后面的参数...(楼主表示不懂,但是都是这么写的0.0) dispatch_queue_attr_t myQueue = dispatch_get_global_queue(0, 0); //在派发队列上放置一个子线程的异步操作 dispatch_async(myQueue, ^{ for (int i = 0; i <= 100; i++) { //休眠0.02秒 [NSThread sleepForTimeInterval:0.02]; //获得主线程 dispatch_async(dispatch_get_main_queue(), ^{ //主线程的操作 self.progressView.progress += 0.01; }); } });}
这样子看起来是不是怪怪的,那么组合起来用会显得更加高大上,如下
//更新进程-(void)updateProgress{ //在派发队列中添加子线程异步操作 dispatch_async(dispatch_get_global_queue(0, 0), ^{ for (int i = 0; i <= 100; i++) { //进程休眠0.02秒 [NSThread sleepForTimeInterval:0.02]; //主线程修改进度条 dispatch_async(dispatch_get_main_queue(), ^{ //修改进度条 self.progressView.progress += 0.01; }); } }); }
看一下效果吧
以上看法以及用法属于个人理解,如果有错误,请指正,避免误导其他人,3Q
0 0
- iOS开发-------多线程编程
- iOS开发-多线程编程
- iOS开发------多线程编程(1)
- iOS开发------多线程编程(2)
- [iOS开发]IOS多线程之Block编程
- IOS开发——多线程编程
- iOS开发--多线程编程(一)NSThread
- iOS开发--多线程编程(三)NSOperation
- iOS开发—iOS多线程编程之NSThread的使用
- iOS-----IOS多线程开发
- 在iOS开发中利用GCD进行多线程编程
- 在iOS开发中利用GCD进行多线程编程
- IOS开发 GCD多线程编程技术(一)
- IOS开发 GCD多线程编程技术(二)
- iOS 开发中,多线程编程GCD的常用方法总结
- iOS开发--多线程编程(二)NSThread买票
- iOS开发探索-多线程(NSThread、NSOperation、GCD)编程浅谈
- iOS开发——多线程编程(GCD)
- 文章标题
- 如何用kill安全杀掉clusterware
- IOS Quartz 各种绘制图形用法---实现画图片、写文字、画线、椭圆、矩形、棱形等
- W3school学习笔记之CSS
- 黑马程序员——java学习笔记--数组
- iOS开发-------多线程编程
- 黑马程序员——java学习笔记--字符串
- Java内存模型之运行时数据区域
- 文章标题
- 外网访问内网服务器设置方法+远程图形终端
- Android进阶之“再按一次返回键退出程序”实现
- 黑马程序员——抽象类,接口总结
- 合成和聚合的关系
- 3617 Best Cow Line【贪心】