前言:
多线程编程是防止主线程堵塞,增加运行效率等等的最佳方法,而原始的多线程方法编程方法有很多毛病,包括线程锁死等。在Cocoa中,Apple提供了NSOperation这个类,提供了一个优秀的多线程编写方法。
首先是建立NSOperationQueue和NSOperation、NSOperationQueue会建立一个线程管理器。每一个加入到线程的NSOperation会有序的执行。
一、什么是NSOperation?
NSOperation是除NSThread之外的第二种多线程编程方式。
采用NSOperation(线程操作,通常用他的子类)和NSOperationQueue(线程队列)搭配来做多线程的开发。采用NSOperation指定一个操作。把这个操作放到线程队列(线程池)中。让线程队列来安排它的生命周期。
二、NSOperation与NSThread有什么区别?
①、NSThread需要启动,也就是说需要费心管理线程的生命周期,而采用NSOperation只需要将线程放到线程队列中即可、线程队列负责管理、执行所有的线程操作。
②、管理线程的最大并发数,也就是同时执行任务数。
③、控制线程之间的依赖关系,NSOperation之间可以设置依赖以保证顺序执行,比如一定要让操作1执行完后,才能执行操作2,线程之间不能相互依赖。比如A依赖B、B又依赖A。
④、队列的取消、暂停、恢复
下面代码实际展示NSOperation的应用
使用NSOperationQueue的过程:
1)建立一个NSOperationQueue的对象
2)建立一个NSOperation(一般都是用它的子类)对象
3)将NSOperation对象加入到NSOperationQueue中
NSOperation开发总共有三种方式
1、NSInvocationIOperation和NSOperationQueue搭配进行多线程开发
2、NSBlockOperation和NSOperationQueue搭配开发多线程
3、用自定义与NSOperation的类与NSOperation搭配
#pragma mark****此处练习是利用多线程加载网络图片******
步骤:
1.创建视图
2.创建线程队列
3.创建线程
4.将线程放到线程队列中
5.在子线程加载网络资源
6.回到主线程
7.更新UI
*********************************************
//
// ViewController.m
// NSOperation的复习
//
// Created by scsys on 16/3/3.
// Copyright © 2016年 pls. All rights reserved.
//
#import "ViewController.h"
//宏定义一个网络资源文件的路径
#define kurl @"http://store.storeimages.cdn-apple.com/8748/as-images.apple.com/is/image/AppleInc/aos/published/images/s/38/s38ga/rdgd/s38ga-rdgd-sel-201601?wid=848&hei=848&fmt=jpeg&qlt=80&op_sharpen=0&resMode=bicub&op_usm=0.5,0.5,0,0&iccEmbed=0&layer=comp&.v=1454777389943"
@interface ViewController ()
{
UIImageView *imageView;
}
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//利用多线程加载一张网络图片
// 步骤:
/*
1、创建一个视图
2、创建一个线程队列
3、创建一个线程
4、将线程添加到线程队列中
5、在子线程中加载网络资源
6、回到主线程
7、更新UI
*/
//1.创建一个视图、此处一般将视图设为全局变量
imageView = [[UIImageView alloc]initWithFrame:CGRectMake(50, 200, 200, 200)];
// 让加载的网络图片根据imageView的大小自适应
imageView.contentMode = UIViewContentModeScaleAspectFit;
[self.view addSubview:imageView];
//2、创建一个线程队列
// 在此处直接用了一个new,相当于直接给它alloc、init了。不用写的那么复杂
NSOperationQueue *operationQueue = [NSOperationQueue new];
//3、创建一个线程,此处用NSOperation的子类(NSInvocationOperation)
// 创建一个NSInvocationOperation对象,并初始化到方法。
// 在这里selcetor参数后面的值是你想在另外一个线程中运行的方法(函数,Method)
// 在这里object后的值是想传递给前面方法的数据
NSInvocationOperation *invocationOperation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(loadResource) object:nil];
//4、将线程添加到线程队列中
// 下面将我们建立的操作“operation”加入到本地程序的共享队列中,(加入后方法就会立刻被执行)
[operationQueue addOperation:invocationOperation];
}
//5、在子线程中加载网络资源
-(void)loadResource{
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:kurl ]];
UIImage *image = [UIImage imageWithData:data];
//6、回到主线程
[[NSOperationQueue mainQueue]addOperationWithBlock:^{
//7、更新UI
imageView.image = image;
}];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
#pragma mark ----NSOperation的第二种开发方式-------NSBlockOperation
#pragma mark=====NSOperation的第二种开发方式==========
-(void)viewDidLoad{
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
self.edgesForExtendedLayout = UIRectEdgeNone ;
//1、创建一个视图
imageView = [[UIImageView alloc]initWithFrame:CGRectMake(50, 50, 200, 200)];
imageView.contentMode = UIViewContentModeScaleAspectFit;
[self.view addSubview:imageView];
//2、创建一个县城队列
NSOperationQueue *operationQueue = [NSOperationQueue new];
//3、创建一个线程
NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
//5、加载网络资源文件
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:kurl]];
UIImage *image = [UIImage imageWithData:data];
//6、回到主线程
[[NSOperationQueue mainQueue]addOperationWithBlock:^{
// 7、更新UI
imageView.image = image;
}];
}];
//4、将线程放到线程队列中
[operationQueue addOperation:blockOperation];
}