多线程初学
多线程 每个应用程序的内部,存在一个或多个执行线程,它同时或在一个几乎同时执行不同的操作
进程与线程:每个系统允许的程序都是一个进程,每个进程里面包含了一到多个线程
线程是一组指令的集合,程序中一个单一的顺序控制流程,是一个程序中,独立允许的程序片段(一个应用程序里面 单一的顺序控制执行的一个任务)
程序允许后,系统会创建一个叫做(main)主线程的线程,所有的UI控件都必须运行在主线程中,所以也有人叫它UI线程
如果将所有的任务都放在主线程中,容易造成UI阻塞
多线程:在同一个应用程序内 同时运行多个线程 完成不同的工作 叫做多线程
为什么要使用多线程:单线程的应用程序中,代码沿直线执行 只有前面的代码执行完了,才会取执行后面的代码 中间这段时间,实际上就处于等待状态 当用户执行某项操作的时候 比如上传文件 或则下载文件 主线程会执行这个任务 知道上传结束后 主线程才能继续后面的工作 在这个短时间内 主线程处于忙碌状态 不会对用户的请求作出任何反应 最直观的感受就是界面卡死 特别是操作这个任务需要大量的时间的时候就更明显
iOS中有几种多线程方式
iOS中有三种多线程策略供开发者使用 :NSThread、NSOpration(基类不可以直接使用 只能使用它的子类)GCD(Grand Central Dispatch)
GCD 苹果 推荐的一种 实现 多线程的方式
轻量级:对系统框架的依赖性的程度
NSThread:是这三种策略里面相对轻量级的,需要自己去管理他的生命周期,以及线程之间的同步,以及线程之间的同步,线程共享同一应用程序的部分内存空间,他们拥有对数据相同的访问权限,所以得协调多个线程对同一数据的访问,常用的做法是在访问之前加锁,这回导致一定的性能开销
NSThread的创建和启动:
NSThread的创建主要由两种直接的方式:
1、init 需要手动开启
2、类方法 不用手动开启 自动开启
NSOperation 是一个基类(抽象类)不能直接使用 必须使用它的子类
他默认是在 当前线程 进行操作 如果单独使用NSOperation 必须手动启动
常与NSOperationQueue一起使用 在于线程队列一起使用 会自动开辟线程 进行操作 不用手动启动
1、NSOperation 系统提供了两个子类:NSInvocationOperation 和 NSBlockOperation
2、自定义的子类NSOperation的子类
NSBlockOperation 操作数大于1 也会开辟线程去执行操作
单一使用Operation它是同步执行
NSOperation类是用来封装与单个任务相关的代码和数据的抽象类,因为它是抽象的,你不能直接使用这个类,而是继承或使用系统定义的子类(NSInvocationOperation或NSBlockOperation)之一来执行实际任务
//开辟线程 去执行另一任务 执行完毕之后 主线程 需要的数据 得再次更新
//每一个线程 都是 独立的代码片段 当主线程 触发下载任务 开辟另一个线程的时候 (主线程会继续执行) 子线程也会独立执行 (主线程 不知道 子线程 什么时候 执行完毕)
//执行一个耗时的操作
- (void)downLoad:(UIButton *)sender{
// 为了防止下载任务 阻塞主线程 咱们 开辟了一个子线程 去执行 耗时的任务
// 使用 alloc init 必须手动启动管理
NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(downLoadOperation) object:nil];
// 给线程取个名字
thread.name = @"下载图片线程";
[thread start];
// 多个线程 同时访问 一个数据
NSThread *thread2 = [[NSThread alloc]initWithTarget:self selector:@selector(downLoadOperation) object:nil];
thread2.name = @"下载图片线程2";
[thread2 start];
// detachNewThreadSelector 不用 手动 开启线程
// [NSThread detachNewThreadSelector:@selector(downLoadOperation) toTarget:self withObject:nil];
}
-(void)downLoadOperation{
NSLog(@"下载线程:%@", [NSThread currentThread]);
// 模拟 下载 耗时任务的操作
sleep(5);
// 当操作完毕之后 刷新UI 在主线程里面去刷新
// 从子线程 回到 主线程 去刷新UI界面
[self performSelectorOnMainThread:@selector(updateUI) withObject:nil waitUntilDone:YES];
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://file.bmob.cn/M01/33/41/oYYBAFXcMhaARlGBAABOZfJ7P6Y062.png"]];
imageView.image = [UIImage imageWithData:data];
}
- (void)updateUI{
NSLog(@"当前线程:%@", [NSThread currentThread]);
imageView.backgroundColor =[UIColor redColor];
}