总结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 }];
多线程内容基本完成,,,,,,我只是小白一只,欢迎大家补充交流,共同提高
- 总结iOS 多线程学习过程六
- 总结iOS 多线程学习过程一
- 总结iOS 多线程学习过程二
- 总结iOS 多线程学习过程三
- 总结iOS 多线程学习过程四
- 总结iOS 多线程学习过程五
- IOS 多线程-GCD学习总结
- 项目管理学习笔记之六人力资源管理过程总结
- MyBatis学习总结(六)——调用存储过程
- MyBatis学习总结(六)——调用存储过程
- MyBatis学习总结(六)——调用存储过程
- MyBatis学习总结(六)——调用存储过程
- MyBatis学习总结(六)——调用存储过程
- MyBatis学习总结(六)——调用存储过程
- MyBatis学习总结(六)——调用存储过程
- MyBatis学习总结(六)——调用存储过程
- MyBatis学习总结(六)——调用存储过程
- MyBatis学习总结(六)——调用存储过程
- 0020回文的一种实现方法
- git tag的用法
- linux c mysql
- HDU 1114 Piggy-Bank(完全背包问题)
- 错误笔记
- 总结iOS 多线程学习过程六
- 笔记六(脉冲运动)
- 使用stat()函数判断文件类型
- 文件输入和输出流
- HTML5中新表单元素及表单验证
- poj1155 TELE(树形dp+背包)
- 冒号用法
- java添加删除cookie
- bzoj-3676 回文串