总结iOS 多线程学习过程六

来源:互联网 发布:mac的excel数据有效性 编辑:程序博客网 时间:2024/04/28 15:20

iOS多线程的老二 ---- NSOperation

老二存在的意义:

1. 是完全面向对象

2. 包含GCD 无法实现的功能:

    1) 指定使用线程的个数

    2) 任务间的依赖关系

选择 GCD 还是 NSoperation?

能用老大用老大,老大不行老二上.....

首先介绍 NSOperation 的一个子类:

------ NSInvocationOperation

上代码:

- (void)viewDidLoad {    [super viewDidLoad];    }//non-main queue- (IBAction)invocationSync:(id)sender {    //1.创建非主队列    //2.创建NSInvocationOperation对象    NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(printPlus) object:nil];    //3.指定执行的任务(直接添加到主队列中执行;sync同步执行)    [operation start];}- (IBAction)invocationAsync:(id)sender {    //1.创建非主队列    NSOperationQueue *queue = [[NSOperationQueue alloc] init];    //2.创建NSInvocationOperation对象    NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(printPlus) object:nil];    NSInvocationOperation *secondOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(printMinus) object:nil];    //3.指定执行的任务(添加的瞬间就异步执行)    [queue addOperation:operation];    [queue addOperation:secondOperation];    NSLog(@"执行完毕");    }- (void)printMinus {    for (int i = 0; i < 5; i++) {        [NSThread sleepForTimeInterval:1];        NSLog(@"---------%@", [NSThread currentThread]);    }}- (void)printPlus {    for (int i = 0; i < 5; i++) {        [NSThread sleepForTimeInterval:1];        NSLog(@"++++++++++%@", [NSThread currentThread]);    }}

执行结果:

2015-11-16 20:27:51.460 pthread[2116:198665] ++++++++++<NSThread: 0x7fac28605c90>{number = 1, name = main}
2015-11-16 20:27:52.461 pthread[2116:198665] ++++++++++<NSThread: 0x7fac28605c90>{number = 1, name = main}
2015-11-16 20:27:53.461 pthread[2116:198665] ++++++++++<NSThread: 0x7fac28605c90>{number = 1, name = main}
2015-11-16 20:27:54.462 pthread[2116:198665] ++++++++++<NSThread: 0x7fac28605c90>{number = 1, name = main}
2015-11-16 20:27:55.463 pthread[2116:198665] ++++++++++<NSThread: 0x7fac28605c90>{number = 1, name = main}
2015-11-16 20:27:57.283 pthread[2116:198665] 执行完毕
2015-11-16 20:27:58.305 pthread[2116:198785] ---------<NSThread: 0x7fac2850a0e0>{number = 2, name = (null)}
2015-11-16 20:27:58.305 pthread[2116:198782] ++++++++++<NSThread: 0x7fac286132f0>{number = 3, name = (null)}
2015-11-16 20:27:59.373 pthread[2116:198782] ++++++++++<NSThread: 0x7fac286132f0>{number = 3, name = (null)}
2015-11-16 20:27:59.373 pthread[2116:198785] ---------<NSThread: 0x7fac2850a0e0>{number = 2, name = (null)}
2015-11-16 20:28:00.446 pthread[2116:198785] ---------<NSThread: 0x7fac2850a0e0>{number = 2, name = (null)}
2015-11-16 20:28:00.446 pthread[2116:198782] ++++++++++<NSThread: 0x7fac286132f0>{number = 3, name = (null)}
2015-11-16 20:28:01.521 pthread[2116:198785] ---------<NSThread: 0x7fac2850a0e0>{number = 2, name = (null)}
2015-11-16 20:28:01.521 pthread[2116:198782] ++++++++++<NSThread: 0x7fac286132f0>{number = 3, name = (null)}
2015-11-16 20:28:02.595 pthread[2116:198785] ---------<NSThread: 0x7fac2850a0e0>{number = 2, name = (null)}
2015-11-16 20:28:02.595 pthread[2116:198782] ++++++++++<NSThread: 0x7fac286132f0>{number = 3, name = (null)}

由结果可知,,当使用 start 方法启动时,他是在默认的线程中的,,而加到自己建的 NSOperationQueue *queue 中是在子线程中执行的.

第二个子类:

------ NSBlockOperation

上代码:

<span style="font-size:18px;">- (void)viewDidLoad {    [super viewDidLoad];    }- (IBAction)blockSync:(id)sender {    //创建对象(方式一)    NSBlockOperation *operation = [NSBlockOperation new];    //添加任务    [operation addExecutionBlock:^{        NSLog(@"下载图片111111%@", [NSThread currentThread]);    }];    [operation addExecutionBlock:^{        NSLog(@"下载图片2222%@", [NSThread currentThread]);    }];    [operation addExecutionBlock:^{        NSLog(@"下载图片3333%@", [NSThread currentThread]);    }];    //执行任务(同步)    //第一个操作由主线程做; 剩余操作由子线程做    [operation start];}- (IBAction)blockAsync:(id)sender {    //1.创建一个非主队列    NSOperationQueue *queue = [[NSOperationQueue alloc] init];        //2.创建操作对象(方式二)    NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{        NSLog(@"下载图片1111%@", [NSThread currentThread]);    }];    NSBlockOperation *otherOperation = [NSBlockOperation blockOperationWithBlock:^{        NSLog(@"下载图片2222%@", [NSThread currentThread]);    }];    //3.执行操作(添加操作到非主队列)    [queue addOperation:operation];    [queue addOperation:otherOperation];    NSLog(@"下载完毕");}</span>

执行结果:

2015-11-16 20:36:55.236 pthread[2150:203509] 下载图片111111<NSThread: 0x7fb1527050d0>{number = 1, name = main}
2015-11-16 20:36:55.236 pthread[2150:204161] 下载图片2222<NSThread: 0x7fb1526542d0>{number = 3, name = (null)}
2015-11-16 20:36:55.236 pthread[2150:204164] 下载图片3333<NSThread: 0x7fb152422990>{number = 2, name = (null)}
2015-11-16 20:37:01.211 pthread[2150:203509] 下载完毕
2015-11-16 20:37:01.211 pthread[2150:204161] 下载图片1111<NSThread: 0x7fb1526542d0>{number = 3, name = (null)}
2015-11-16 20:37:01.211 pthread[2150:204164] 下载图片2222<NSThread: 0x7fb152422990>{number = 2, name = (null)}

要注意NSBlockOperation 中 start 的方法,他是把第一个交由主线程,剩下的在子线程中完成

由上面两个例子,你应该也知道了 NSOperation 是不创建对象的,因为他是个抽象类,创建对象都有他的子类完成

-----------------------------------------分割线-----------------------------------------

现在补充 NSOperation 比 GCD多出来的功能:

上代码:

- (void)viewDidLoad {    [super viewDidLoad];}- (IBAction)setConcurrentCount:(id)sender {    //创建非主队列    NSOperationQueue *queue = [NSOperationQueue new];    //设定同时执行任务的个数(起多少子线程)    queue.maxConcurrentOperationCount = 2;    //创建任务    NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{        NSLog(@"下载图片11111%@",[NSThread currentThread]);    }];    NSBlockOperation *secondOperation = [NSBlockOperation blockOperationWithBlock:^{        NSLog(@"下载图片2222%@", [NSThread currentThread]);    }];    NSBlockOperation *thirdOperation = [NSBlockOperation blockOperationWithBlock:^{        NSLog(@"下载图片333%@", [NSThread currentThread]);    }];    NSBlockOperation *forthOperation = [NSBlockOperation blockOperationWithBlock:^{        NSLog(@"下载图片4444%@",[NSThread currentThread]);    }];    NSBlockOperation *fifthOperation = [NSBlockOperation blockOperationWithBlock:^{        NSLog(@"下载图片5555%@", [NSThread currentThread]);    }];    NSBlockOperation *sixthOperation = [NSBlockOperation blockOperationWithBlock:^{        NSLog(@"下载图片666%@", [NSThread currentThread]);    }];    NSBlockOperation *seventhOperation= [NSBlockOperation blockOperationWithBlock:^{        NSLog(@"下载图片777%@", [NSThread currentThread]);    }];    //执行任务(添加到非主队列)    NSArray *array = @[operation, secondOperation, thirdOperation, forthOperation, fifthOperation, sixthOperation, seventhOperation];    [queue addOperations:array waitUntilFinished:YES];}- (IBAction)setDependency:(id)sender {    //设定非主队列中的任务的依赖关系    /*task1, task2, task3 ---> 三个同时执行     需求1: task1 + task2 --> task3     task3 依赖 task1     task3 依赖 task2     需求2: task2 --> task1 + task3     task1 依赖 task2     task3 依赖 task2     */    //1.创建非主队列    NSOperationQueue *queue = [NSOperationQueue new];    //2.创建操作(任务/子线程)    NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{        NSLog(@"下载图片11111");    }];    NSBlockOperation *secondOperation = [NSBlockOperation blockOperationWithBlock:^{        NSLog(@"下载图片2222");        [NSThread sleepForTimeInterval:5];    }];    NSBlockOperation *thirdOperation = [NSBlockOperation blockOperationWithBlock:^{        NSLog(@"下载图片333");    }];    //3.设定依赖关系    [thirdOperation addDependency:operation];    [thirdOperation addDependency:secondOperation];    //4.执行任务    [queue addOperation:operation];    [queue addOperation:secondOperation];    [queue addOperation:thirdOperation];}- (IBAction)returnMainThread:(id)sender {    //方式三: 回到主线程 (有且仅有一个主队列)    //非主队列    NSOperationQueue *queue = [NSOperationQueue new];    //添加任务(子线程)    [queue addOperationWithBlock:^{        NSLog(@"开始下载图片%@", [NSThread currentThread]);        //回到主线程        [[NSOperationQueue mainQueue] addOperationWithBlock:^{            NSLog(@"显示/加载图片%@", [NSThread currentThread]);        }];    }];        }
执行结果:

2015-11-16 20:43:50.972 Demo03-Block-Dependency[2195:208141] 下载图片2222<NSThread: 0x7fae0af06ac0>{number = 2, name = (null)}
2015-11-16 20:43:50.972 Demo03-Block-Dependency[2195:208144] 下载图片11111<NSThread: 0x7fae0ac26350>{number = 3, name = (null)}
2015-11-16 20:43:50.973 Demo03-Block-Dependency[2195:208144] 下载图片333<NSThread: 0x7fae0ac26350>{number = 3, name = (null)}
2015-11-16 20:43:50.973 Demo03-Block-Dependency[2195:208149] 下载图片4444<NSThread: 0x7fae0ae70bf0>{number = 4, name = (null)}
2015-11-16 20:43:50.973 Demo03-Block-Dependency[2195:208144] 下载图片5555<NSThread: 0x7fae0ac26350>{number = 3, name = (null)}
2015-11-16 20:43:50.973 Demo03-Block-Dependency[2195:208141] 下载图片666<NSThread: 0x7fae0af06ac0>{number = 2, name = (null)}
2015-11-16 20:43:50.973 Demo03-Block-Dependency[2195:208173] 下载图片777<NSThread: 0x7fae0ae71000>{number = 5, name = (null)}
2015-11-16 20:43:59.163 Demo03-Block-Dependency[2195:208173] 下载图片11111
2015-11-16 20:43:59.163 Demo03-Block-Dependency[2195:208144] 下载图片2222
2015-11-16 20:44:04.239 Demo03-Block-Dependency[2195:208144] 下载图片333
2015-11-16 20:44:19.827 Demo03-Block-Dependency[2195:208561] 开始下载图片<NSThread: 0x7fae0ac41ed0>{number = 6, name = (null)}
2015-11-16 20:44:19.828 Demo03-Block-Dependency[2195:208051] 显示/加载图片<NSThread: 0x7fae0ad040a0>{number = 1, name = main}

观察结果中,设置了线程并发个数后,单位时间内确实只有两个线程在工作;;;而依赖关系的设定能跟好的控制线程之间的先后顺序;;;最后是回到主线程的方法.


再来个回到主线程方法总结,因为前面少说了一种,现在在总结:

①:NSThread ---- [self performSelectorOnMainThread: withObject: waitUntilDone:] (之前少的);

②:GCD ---- dispatch_async(dispatch_get_main_queue(),^{    //code    });

③:NSOperation ---- [[NSOperationQueue mainQueue] addOperationWithBlock:^{    //code   }];

多线程内容基本完成,,,,,,我只是小白一只,欢迎大家补充交流,共同提高

0 0
原创粉丝点击