什么是多线程?
一个进程的开始阶段系统会分配一个主线程进行正常的工作,工作过程中是依次执行的,只有这个任务执行完毕的时候才能执行下一个任务,两个或多个任务不能同时执行。这样的工作效率是低效的,因此就引入了多线程,能够利用iPhone设备多核的优势同时并发的处理多个事件。
三种多线程技术:
1.NSThread
2.NSOperation、NSOperationQueue
3.GCD
分析三种技术
这三种技术从上到下封装性逐步降低、造成逐步复杂、高效性逐步提升,GCD是基于C语言开发的,最底层、用起来比较麻烦些,但效率最高。
NSThread:
- 优点:轻量级、比较简单
- 缺点:需要程序员管理线程的生命周期、线程同步、加锁、睡眠以及唤醒等。线程同步对数据的加锁会有一定的系统开销
NSOperation:
- 不需要像NSThread那样关心线程管理、数据同步的事情、程序员的主要工作放在执行的操作上
GCD:
- GCD是苹果在iOS4.0以后使用的一种技术、比上两个技术更强大和高效
- 操作起来比较麻烦些、基于C语言开发的
深入学习之前我们先看一个例子看下多线程的强大
假设性开发:我们输入账号密码登录QQ后,会出现我们的昵称、等级、聊天记录、好友图片以及自己的图片。我们知道:图片的加载是最消耗性能、最耗时和耗费流量、当用户处于2G/3G或者WIFI状态非常不好的状态,倘若我们不引进多线程会怎么样应该是登录后用户迟迟不能进行操作,唯有所有数据都加载完毕之后才能进行,这样的用户体验是非常糟糕的。
下面用伪代码进行模拟 ,我们在上面加入时间宏函数,测试一下登录成功到可以操作所需时间
#define STARTTIME NSDate *startTime=[NSDate date];
#define ENDTIME NSLog(@"Time: %f", -[startTime timeIntervalSinceNow]);
STARTTIME//开始计时
NSLog(@"用户登录成功----");
NSLog(@"正在加载用户昵称----");
for(int i=0;i<10000;i++)
{
NSLog(@"正在加载用户好友的数据信息");
}
for(int i=0;i<10000;i++)
{
NSLog(@"正在加载用户好友的图片信息");
}
for (int i=0; i<10000; i++) {
NSLog(@"正在加载用户与好友的聊天信息");
}
NSLog(@"所有加载完毕,用户可以操作了");
ENDTIME//结束计时
经过模拟,发现,所有操作在主线程中进行,至少用户在登录9.5秒内是没法操作的,这样的操作跟安卓手机有什么区别?卡的XX一样,谁还用iPhone?不明觉厉之后就该好好研究一下多线程啦!
好啦,我们开始逐步学习这三种方法:
NSThread:
分三步轻轻松松实现多线程:
创建一个线程类
NSThread *thread1=[[NSThread alloc]initWithTarget:self selector:@selector(startLoad1) object:nil];
2.实现相应的方法 ,把耗时操作放入多线程方法中
-(void)startLoad1 { for(int i=0;i<10000;i++) { NSLog(@"正在加载用户好友的数据信息"); } }
3.开启线程
[thread1 start];
于是上面的代码被我们改为:
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"用户登录成功----");
NSLog(@"正在加载用户昵称----");
//申请开辟线程
NSThread *thread1=[[NSThread alloc]initWithTarget:self selector:@selector(startLoad1) object:nil];
NSThread *thread2=[[NSThread alloc]initWithTarget:self selector:@selector(startLoad2) object:nil];
NSThread *thread3=[[NSThread alloc]initWithTarget:self selector:@selector(startLoad3) object:nil];
[thread1 start];//开启线程
[thread2 start];
[thread3 start];
NSLog(@"所有加载完毕,用户可以操作了");
}
-(void)startLoad1//实现线程方法
{
for(int i=0;i<10000;i++)
{
NSLog(@"正在加载用户好友的数据信息");
}
}
-(void)startLoad2
{
for(int i=0;i<10000;i++)
{
NSLog(@"正在加载用户好友的图片信息");
}
}
-(void)startLoad3
{
for (int i=0; i<10000; i++) {
NSLog(@"正在加载用户与好友的聊天信息");
}
}
只要0.001338秒,对比9.5秒,多么可怕的数字呀!不明觉厉!多线程强大吧!
上面我们需要经历三步,才能创建一个子线程,再说一种NSThread的另一种方法吧,只需要两步,不需要程序员调用star函数开始线程,
创建并自动启动
[NSThread detachNewThreadSelector:@selector(startLoad1) toTarget:self withObject:nil];
NSThread 的其他边角知识:
//取消线程
- (void)cancel;
//启动线程
- (void)start;
//判断某个线程的状态的属性
@property (readonly, getter=isExecuting) BOOL executing;
@property (readonly, getter=isFinished) BOOL finished;
@property (readonly, getter=isCancelled) BOOL cancelled;
//设置和获取线程名字
-(void)setName:(NSString *)n;
-(NSString *)name;
//获取当前线程信息
+ (NSThread *)currentThread;
//获取主线程信息
+ (NSThread *)mainThread;
//使当前线程暂停一段时间,或者暂停到某个时刻
+ (void)sleepForTimeInterval:(NSTimeInterval)time;
+ (void)sleepUntilDate:(NSDate *)date;
限于篇幅的原因(不习惯一个博客写的太长,这样读者会感觉太累),下一节我们将介绍NSOperation、NSOperationQueue