iOS-多线程--介绍NSOperration
一个NSOperation对象就代表一个操作,对象相当于GCD中的block。
一、NSOperation的作用:
配合使用NSOperation和NSOperationQueue也能实现多线程。
二、NSOperation和NSOperationQueue实现多线程的步骤:
步骤1: 先将需要执行的操作封装到一个NSOperation对象中;
步骤2: 系统会自动将NSOperationQueue中得NSOperation取出来;
步骤3: 将取出来的NSOperation封装的操作放到一条线程中执行。
三、NSOperation的子类
NSOperation是个抽象类,并不具备封装操作的能力,必须使用它的子类
四、使用NSOperation子类的方式有3种:
1> NSInvocationOperation
2> NSBlockOperation
3> 自定义子类继承NSOperation,实现内部相应的方法
五、使用方式:
方式1:用NSInvocationOperation, 代码如下:
重要级别:演示
1 - (void)viewDidLoad 2 { 3 [super viewDidLoad]; 4 5 // 创建队列 6 NSOperationQueue *queue = [[NSOperationQueue alloc] init]; 7 8 // 创建操作 9 NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download) object:nil]; 10 // operation直接调用start,是同步执行(在当前线程执行操作) 11 // [operation start]; 12 13 // 添加操作到队列中,会自动异步执行 (如果不将operation加到队列中,直接[operation start];执行的话,就相当于调用 [self download], 不是异步执行,是在主线程执行的;添加到操作队列中,会开启一个新的线程,异步执行) 14 15 [queue addOperation:operation]; 16 } 17 18 - (void)download 19 { 20 NSLog(@"download-----%@", [NSThread currentThread]); 21 }
方式2. 用NSBlockOperation,代码如下:
重要级别:了解(test1 test2 里面的是了解)
- (void)viewDidLoad { [super viewDidLoad]; [self test2]; }
- (void)test2 { NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"---下载图片----11---%@", [NSThread currentThread]); }]; [operation1 addExecutionBlock:^{ NSLog(@"---下载图片----12---%@", [NSThread currentThread]); }]; NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"---下载图片----2---%@", [NSThread currentThread]); }]; NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"---下载图片----3---%@", [NSThread currentThread]); }]; NSBlockOperation *operation4 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"---下载图片----4---%@", [NSThread currentThread]); }]; // 1.创建队列 NSOperationQueue *queue = [[NSOperationQueue alloc] init]; // 相当于GCD的全局并发队列,下面的四个操作都在新开启的线程中异步执行 // 主队列 // NSOperationQueue *queue = [NSOperationQueue mainQueue]; // 相当于GCD的主队列,下面的四个操作都在主队列执行 // 2.添加操作到队列中(自动异步执行) [queue addOperation:operation1]; [queue addOperation:operation2]; [queue addOperation:operation3]; [queue addOperation:operation4]; }
- (void)test { NSBlockOperation *operation = [[NSBlockOperation alloc] init]; [operation addExecutionBlock:^{ NSLog(@"---下载图片----1---%@", [NSThread currentThread]); }]; [operation addExecutionBlock:^{ NSLog(@"---下载图片----2---%@", [NSThread currentThread]); }]; [operation addExecutionBlock:^{ NSLog(@"---下载图片----3---%@", [NSThread currentThread]); }]; [operation start]; // 任务数量 > 1,才会开始异步执行(不然的话就是同步执行,在主线程做的) }
## 下面的要掌握 ##
- (void)viewDidLoad { [super viewDidLoad]; } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { NSOperationQueue *queue = [[NSOperationQueue alloc] init]; [queue addOperationWithBlock:^{ // 1.异步下载图片 NSURL *url = [NSURL URLWithString:@"http://d.hiphotos.baidu.com/image/pic/item/37d3d539b6003af3290eaf5d362ac65c1038b652.jpg"]; NSData *data = [NSData dataWithContentsOfURL:url]; UIImage *image = [UIImage imageWithData:data]; // 2.回到主线程,显示图片 // [self performSelectorOnMainThread:<#(SEL)#> withObject:<#(id)#> waitUntilDone:<#(BOOL)#>]; // dispatch_async(dispatch_get_main_queue(), ^{ // // }); [[NSOperationQueue mainQueue] addOperationWithBlock:^{ self.imageView.image = image; }]; }]; } - (void)dependency { /** 假设有A、B、C三个操作,要求: 1. 3个操作都异步执行 2. 操作C依赖于操作B 3. 操作B依赖于操作A */ // 1.创建一个队列(非主队列) NSOperationQueue *queue = [[NSOperationQueue alloc] init]; // 2.创建3个操作 NSBlockOperation *operationA = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"A1---%@", [NSThread currentThread]); }]; // [operationA addExecutionBlock:^{ // NSLog(@"A2---%@", [NSThread currentThread]); // }]; // // [operationA setCompletionBlock:^{ // NSLog(@"AAAAA---%@", [NSThread currentThread]); // }]; NSBlockOperation *operationB = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"B---%@", [NSThread currentThread]); }]; NSBlockOperation *operationC = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"C---%@", [NSThread currentThread]); }]; // 设置依赖 [operationB addDependency:operationA]; [operationC addDependency:operationB]; // 3.添加操作到队列中(自动异步执行任务) [queue addOperation:operationC]; [queue addOperation:operationA]; [queue addOperation:operationB]; } - (void)maxCount { // 1.创建一个队列(非主队列,会创建新的线程) NSOperationQueue *queue = [[NSOperationQueue alloc] init]; // 2.设置最大并发(如果设置为3,则最多同时并发执行3个任务) queue.maxConcurrentOperationCount = 3; // 如果设置为1,那么下面的任务是在新线程中依次执行的。 // 3.添加操作到队列中(自动异步执行任务,并发)
// 下面五个操作都异步执行,如果有的操作要在方法里面执行,可以用 操作5 这种形式去实现.
// 操作1 NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"下载图片1---%@", [NSThread currentThread]); }];
// 操作2 NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"下载图片2---%@", [NSThread currentThread]); }];
// 操作3 NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"下载图片3---%@", [NSThread currentThread]); }];
// 操作4 NSBlockOperation *operation4 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"下载图片4---%@", [NSThread currentThread]); }];
// 操作5 NSInvocationOperation *operation5 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download) object:nil]; [queue addOperation:operation1]; [queue addOperation:operation2]; [queue addOperation:operation3]; [queue addOperation:operation4]; [queue addOperation:operation5]; [queue addOperationWithBlock:^{ NSLog(@"下载图片5---%@", [NSThread currentThread]); }]; [queue addOperationWithBlock:^{ NSLog(@"下载图片6---%@", [NSThread currentThread]); }]; [queue addOperationWithBlock:^{ NSLog(@"下载图片7---%@", [NSThread currentThread]); }]; [queue addOperationWithBlock:^{ NSLog(@"下载图片8---%@", [NSThread currentThread]); }]; [queue addOperationWithBlock:^{ NSLog(@"下载图片9---%@", [NSThread currentThread]); }]; [queue cancelAllOperations]; }
- (void)download
{
NSLog(@"download---%@", [NSThread currentThread]);
}
- (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // [queue cancelAllOperations]; // 取消队列中的所有任务(不可恢复) } - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { // [queue setSuspended:YES]; // 暂停队列中的所有任务 } - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate { // [queue setSuspended:NO]; // 恢复队列中的所有任务 } - (void)baseUse { // 1.创建一个队列(非主队列) NSOperationQueue *queue = [[NSOperationQueue alloc] init]; // 2.添加操作到队列中(自动异步执行任务,并发) NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"下载图片1---%@", [NSThread currentThread]); }]; NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"下载图片2---%@", [NSThread currentThread]); }]; [queue addOperation:operation1]; [queue addOperation:operation2]; [queue addOperationWithBlock:^{ NSLog(@"下载图片3---%@", [NSThread currentThread]); }]; // 3个操作并发执行 }
六、操作依赖:
1. NSOperation之间可以设置依赖来保证执行顺序
比如一定要让操作A执行完后,才能执行操作B,可以这么写:
[operationB addDependency:operationA]; // 操作B依赖于操作A
2. 可以在不同queue的NSOperation之间创建依赖关系: