ios 中gcd功能还是很强大的,但是gcd都是c函数,使用的时候可能总是感觉不是很方便。那么有没有oc实现的呢,当然有了,就是NSOperation和NSOperationQueue,其实它们就是对gdc的包装。下面我就来看一下他们的使用
NSOperation是一个抽象类,不能用来封装操作。只能用的他的子类来封装。我们有三种方式来封装分别是:
下面我们主要说一下前两种情况。
NSInvocationOperation
-(void)invocationOperationTest{
*op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(task1:) object:@"mainQueue"];
[op1 start];
NSInvocationOperation *op2 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(task1:) object:@"otherQueue"];
NSOperationQueue * opQueue = [[NSOperationQueue alloc]init];
[opQueue addOperation:op2];
}
-(void)task1:(NSString*)param{
for(int i=0; i<2;i++){
[NSThread sleepForTimeInterval:2];
NSLog(@"param:%@,thread:%@",param,[NSThread currentThread]);
}
}
执行后的log是这样的:
param:mainQueue,thread:
2018-05-18 14:00:34.867450+0800 ocLearner[64622:3297731] param:mainQueue,thread:
2018-05-18 14:00:36.871585+0800 ocLearner[64622:3298021] param:otherQueue,thread:
2018-05-18 14:00:38.872211+0800 ocLearner[64622:3298021] param:otherQueue,thread:
可以看到,如果不把NSInvocationOperation添加到队列中,默认是使用主队列的。因此操作也将在主线程中运行。如果添加到自定义的队列中,将在新开启的线程中运行。
那么,NSBlockOperation是什么情况呢,看代码:
//使用主线程
NSLog(@"mian thread:%@",[NSThread currentThread]);
NSBlockOperation *op1 =[NSBlockOperation blockOperationWithBlock:^{
for(int i=0;i<2;i++){
[NSThread sleepForTimeInterval:2];
NSLog(@"01---%@",[NSThread currentThread]);
}
}];
[op1 start];
//使用addExecutionBlock添加多个操作后有可能不在主线程执行,具体哪个线程由系统决定
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
for(int i=0;i<2;i++){
[NSThread sleepForTimeInterval:2];
NSLog(@"1---%@",[NSThread currentThread]);
}
}];
[op2 addExecutionBlock:^{
for (int i = 0; i < 2; i++) {
[NSThread sleepForTimeInterval:2]; // 模拟耗时操作
NSLog(@"2---%@", [NSThread currentThread]); // 打印当前线程
}
}];
[op2 addExecutionBlock:^{
for (int i = 0; i < 2; i++) {
[NSThread sleepForTimeInterval:2]; // 模拟耗时操作
NSLog(@"2---%@", [NSThread currentThread]); // 打印当前线程
}
}];
[op2 addExecutionBlock:^{
for (int i = 0; i < 2; i++) {
[NSThread sleepForTimeInterval:2]; // 模拟耗时操作
NSLog(@"3---%@", [NSThread currentThread]); // 打印当前线程
}
}];
[op2 addExecutionBlock:^{
for (int i = 0; i < 2; i++) {
[NSThread sleepForTimeInterval:2]; // 模拟耗时操作
NSLog(@"4---%@", [NSThread currentThread]); // 打印当前线程
}
}];
[op2 addExecutionBlock:^{
for (int i = 0; i < 2; i++) {
[NSThread sleepForTimeInterval:2]; // 模拟耗时操作
NSLog(@"5---%@", [NSThread currentThread]); // 打印当前线程
}
}];
[op2 addExecutionBlock:^{
for (int i = 0; i < 2; i++) {
[NSThread sleepForTimeInterval:2]; // 模拟耗时操作
NSLog(@"6---%@", [NSThread currentThread]); // 打印当前线程
}
}];
[op2 addExecutionBlock:^{
for (int i = 0; i < 2; i++) {
[NSThread sleepForTimeInterval:2]; // 模拟耗时操作
NSLog(@"7---%@", [NSThread currentThread]); // 打印当前线程
}
}];
[op2 start];
//使用自定义的OperationQueue,会启用新线程,而且可以不用定义NSBlockOperation,直接在OpertionQueue中添加就可以
NSOperationQueue * opQueue = [[NSOperationQueue alloc]init];
[opQueue addOperationWithBlock:^{
for (int i = 0; i < 2; i++) {
[NSThread sleepForTimeInterval:2]; // 模拟耗时操作
NSLog(@"001---%@", [NSThread currentThread]); // 打印当前线程
}
}];
[opQueue addOperationWithBlock:^{
for (int i = 0; i < 2; i++) {
[NSThread sleepForTimeInterval:2]; // 模拟耗时操作
NSLog(@"002---%@", [NSThread currentThread]); // 打印当前线程
}
}];
[opQueue addOperationWithBlock:^{
for (int i = 0; i < 2; i++) {
[NSThread sleepForTimeInterval:2]; // 模拟耗时操作
NSLog(@"003---%@", [NSThread currentThread]); // 打印当前线程
}
}];
[opQueue addOperationWithBlock:^{
for (int i = 0; i < 2; i++) {
[NSThread sleepForTimeInterval:2]; // 模拟耗时操作
NSLog(@"004---%@", [NSThread currentThread]); // 打印当前线程
}
}];
[opQueue addOperationWithBlock:^{
for (int i = 0; i < 2; i++){
[NSThread sleepForTimeInterval:2]; // 模拟耗时操作
NSLog(@"005---%@", [NSThread currentThread]); // 打印当前线程
}
}];
运行后的Log如图:
2018-05-18 14:06:10.910712+0800 ocLearner[64762:3304313] 01---
2018-05-18 14:06:12.912342+0800 ocLearner[64762:3304313] 01---
2018-05-18 14:06:14.913720+0800 ocLearner[64762:3304313] 2---
2018-05-18 14:06:14.913752+0800 ocLearner[64762:3304688] 1---
2018-05-18 14:06:14.913838+0800 ocLearner[64762:3305021] 2---
2018-05-18 14:06:14.913841+0800 ocLearner[64762:3305022] 3---
2018-05-18 14:06:16.914733+0800 ocLearner[64762:3305021] 2---
2018-05-18 14:06:16.914733+0800 ocLearner[64762:3304688] 1---
2018-05-18 14:06:16.914775+0800 ocLearner[64762:3304313] 2---
2018-05-18 14:06:16.923115+0800 ocLearner[64762:3305022] 3---
2018-05-18 14:06:18.916370+0800 ocLearner[64762:3305021] 4---
2018-05-18 14:06:18.916559+0800 ocLearner[64762:3304688] 5---
2018-05-18 14:06:18.916611+0800 ocLearner[64762:3304313] 6---
2018-05-18 14:06:18.923713+0800 ocLearner[64762:3305022] 7---
2018-05-18 14:06:20.918033+0800 ocLearner[64762:3304313] 6---
2018-05-18 14:06:20.918031+0800 ocLearner[64762:3305021] 4---
2018-05-18 14:06:20.918033+0800 ocLearner[64762:3304688] 5---
2018-05-18 14:06:20.925326+0800 ocLearner[64762:3305022] 7---
2018-05-18 14:06:22.930418+0800 ocLearner[64762:3305021] 003---
2018-05-18 14:06:22.930418+0800 ocLearner[64762:3305022] 001---
2018-05-18 14:06:22.930454+0800 ocLearner[64762:3304688] 002---
2018-05-18 14:06:22.930576+0800 ocLearner[64762:3305295] 005---
2018-05-18 14:06:22.930611+0800 ocLearner[64762:3305294] 004---
2018-05-18 14:06:24.933813+0800 ocLearner[64762:3305022] 001---
2018-05-18 14:06:24.933871+0800 ocLearner[64762:3305295] 005---
2018-05-18 14:06:24.933879+0800 ocLearner[64762:3305021] 003---
2018-05-18 14:06:24.933811+0800 ocLearner[64762:3304688] 002---
2018-05-18 14:06:24.933930+0800 ocLearner[64762:3305294] 004---
可以看到,如果是单个操作,且不添加到自定义队列中,操作将在主线程中运行。如果是多个操作,将由系统决定在哪个线程中运行(这些线程包括主线程),如果是添加到自定义队列,则全部在非主线程中运行。
另外,NSOperation最大的特点是可以设置操作依赖,也就是如果操作A依赖操作B,那么A必须等B完成后才能执行。
用这个函数可以实现:
-(void)addDependency:(NSOperation *)op;
下面来来看一下代码,很简单:
NSOperationQueue *queue =[[NSOperationQueue alloc]init];
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
for(int i=0;i<2;i++){
[NSThread sleepForTimeInterval:2];
NSLog(@"1---%@",[NSThread currentThread]);
}
}];
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
for(int i=0;i<2;i++){
[NSThread sleepForTimeInterval:2];
NSLog(@"2----%@",[NSThread currentThread]);
}
}];
[op2 addDependency:op1];//让op2 依赖于 op1
[queue addOperation:op1];
[queue addOperation:op2];
这个代码无论运行多少次,op1都是在op2之前执行。
好了,先写这么多吧,以后有需要再添加吧。