iOS 【Multithreading-NSOperationQueue及之前部分的拓展延伸(掌握)】

//
//  ViewController.m
//  45-NSOperation(NSOperationQueue)
//
//  Created by 王中尧 on 16/1/22.
//  Copyright © 2016年 黑马. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *imageView;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    // 使用队列下载图片 线程间通信
    
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    [queue addOperationWithBlock:^{
        NSURL *url = [NSURL URLWithString:@"http://pic14.nipic.com/20110522/7411759_164157418126_2.jpg"];
        NSData *data = [NSData dataWithContentsOfURL:url];
        UIImage *image = [UIImage imageWithData:data];
        
    // 从 其他线程回到主线程 显示图片方式

//        方法一:
//        self performSelectorOnMainThread:<#(nonnull SEL)#> withObject:<#(nullable id)#> waitUntilDone:<#(BOOL)#>
        
//        方法二:(GCD)
//        dispatch_async(dispatch_get_main_queue(), ^{
//            <#code#>
//        })
        
//        方法三:(队列)
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            self.imageView.image = image;
        }];
    }];
}

- (void)didReceiveMemoryWarning {
//    此方法是要调用其super的
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
    
//当系统的内存不足时,UIViewController的didReceiveMemoryWarining 方法会被调用,我们可以在didReceiveMemoryWarining 方法里释放掉部分暂时不用的资源。
    
//    [queue cancelAllOperations]; // 取消队列中的所有任务(不可恢复)
//    我们在清理内存的时候就不要干别的事儿了,索性将队列任务全部取消。所以这个方法(cancelAllOperations)一般用在此处(didReceiveMemoryWarning)。
}

- (void)download
{
    NSLog(@"download---%@", [NSThread currentThread]);
}

- (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个操作并发执行
}

// 最大并发数
- (void)maxCount
{
    // 1.创建一个队列(非主队列)
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    
    // 2.设置最大并发(最多同时并发执行3个任务)
    // ★ 这里要注意,是同时并发执行3个任务,关键词在同时,所以说线程可能开了3条,也可能开了4条,这个是不一定的,但是同时并发执行的肯定只有3条线程。而且这里还有一个关键词是最多,所以说可能同时并发2个,不足3个也是可以的。
//    queue.maxConcurrentOperationCount = 3;
    queue.maxConcurrentOperationCount = 3;
    
    // 3.添加操作到队列中(自动异步执行任务,并发)
    //    初始化操作对象(operation),然后将任务添加到操作对象中
    NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"下载图片1---%@", [NSThread currentThread]);
    }];
    NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"下载图片2---%@", [NSThread currentThread]);
    }];
    NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"下载图片3---%@", [NSThread currentThread]);
    }];
    
    // 如果某些操作很简单并且你希望放在block里面,那么就可以这样去写
    NSBlockOperation *operation4 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"下载图片4---%@", [NSThread currentThread]);
    }];
    
    // 如果某一个任务你想放到子线程里,并且这个任务在某个方法里面,那么就可以调用这个方法
    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)dependency
{
    /**
     假设有A、B、C三个操作,要求:
     1. 3个操作都异步执行
     2. 操作C依赖于操作B
     3. 操作B依赖于操作A
     */
    
    NSBlockOperation *operationA = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"A---%@",[NSThread currentThread]);
    }];
    
    // 为operationA再添加一个任务
    [operationA addExecutionBlock:^{
        NSLog(@"AAAAAAA---%@",[NSThread currentThread]);
    }];
    
    // setCompletionBlock 此方法会在operationA执行后接着执行。
    [operationA setCompletionBlock:^{
        NSLog(@"A@A@A@");
    }];
    
    NSBlockOperation *operationB = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"B---%@",[NSThread currentThread]);
    }];
    
    NSBlockOperation *operationC = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"C---%@",[NSThread currentThread]);
    }];
    
    // 设置操作C依赖于操作B,操作B依赖于操作A
    [operationC addDependency:operationB];
    [operationB addDependency:operationA];
    
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    
    // 设置完依赖之后,输出的顺序只与依赖有关
    [queue addOperation:operationB];
    [queue addOperation:operationC];
    [queue addOperation:operationA];
}

// 以下两个方法中一般会添加 暂停/恢复队列任务 的相关代码,目的是为了保证在拖拽的时候不卡顿。
// 拖拽即将开始时调用
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    //    [queue setSuspended:YES]; // 暂停队列中的所有任务
}

// 拖拽即将结束时调用
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
    //    [queue setSuspended:NO]; // 恢复队列中的所有任务
}

@end

你可能感兴趣的:(最大并发数,操作依赖,暂停恢复队列任务,使用队列线程间通信)