您的位置:首页 > 移动开发 > IOS开发

iOS 【Multithreading-线程间通信(NSOperation)/最大并发数/操作依赖/NSOperation优先级】

2016-01-22 21:25 459 查看
//
//  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.创建一个队列(非主队列)。
// 注意:创建队列(默认是并发队列,如果设置最大并发数为1,也就是同时只能执行一个任务,那么就相当于创建了一个串行队列了)
 NSOperationQueue *queue = [[NSOperationQueue alloc] init];

// 2.设置最大并发(最多同时并发执行3个任务)
//   最大并发数默认为-1,意为不受限制。最大并发数也可以设置为0,那么就不会执行任务。
 // ★ 这里要注意,是同时并发执行3个任务,关键词在同时,所以说线程可能开了3条,也可能开了4条,这个是不一定的,但是同时并发执行的肯定只有3条线程。而且这里还有一个关键词是最多,所以说可能同时并发2个,不足3个也是可以的。
//   最大并发数是指执行任务的线程最多是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]);
}];

// 将 操作 添加到 队列 中去
[queue addOperation:operation1];
[queue addOperation:operation2];
[queue addOperation:operation3];

// 往队列中去添加操作的简便写法(创建操作并添加该操作到队列中去,作用一样,但是简便。也有不足之处:如果别的地方想使用该操作,是拿不到的,因为没有一个指针指向该操作对象。上面的都有类似 *operation1 的指针指向,所以可以拿到他)。
[queue addOperationWithBlock:^{
    NSLog(@"下载图片9---%@", [NSThread currentThread]);
}];

}

// 操作依赖
- (void)qwe {
    /**
     假设有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.maxConcurrentOperationCount = 3; // 最大并发数设置为1则顺序执行了
    
    // 设置完依赖之后,输出的顺序只与依赖有关
    [queue addOperation:operationB];
    [queue addOperation:operationC];
    [queue addOperation:operationA];

<div style="margin-left: 30px;">// 注意:一定要在 操作添加到队列 之前 设置依赖。 </div><div style="margin-left: 30px;">// 提示:任务添加的顺序并不能够决定执行顺序,执行的顺序取决于依赖。使用Operation的目的就是为了让开发人员不再关心线程。</div>
}

/*
 (1)设置NSOperation在queue中的优先级,可以改变操作的执⾏优先级

- (NSOperationQueuePriority)queuePriority;
- (void)setQueuePriority:(NSOperationQueuePriority)p;

(2)优先级的取值

NSOperationQueuePriorityVeryLow = -8L,

NSOperationQueuePriorityLow = -4L,

NSOperationQueuePriorityNormal = 0,

NSOperationQueuePriorityHigh = 4,

NSOperationQueuePriorityVeryHigh = 8

说明:优先级高的任务,调用的几率会更大。
 */
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息