ios
来源:互联网 发布:仰恩大学网络教务系统 编辑:程序博客网 时间:2024/06/06 00:38
NSOperation 是抽象类,所以要用子类来进行线程使用;目前是三种方式:
1:NSInvocationOperation
2:NSBlockOperation
3:创建子类继承自 NSOperation
###1:NSInvocationOperation
NSInvocationOperation : 可以理解为是一个为 @selector 包装上任务特性,能够在子线程中执行;
注意事项:
1:单独使用 NSInvocationOperation 不会开启新线程,会在主线程中执行,造成主线程堵塞;
2:创建 NSInvocationOperation 对象之后需要手动开启 start ;
3:此时要结合 NSOperationQueue 组合使用;(衍生出一个问题:GCD , operation 都体现出了线程队列的概念,队列对多线程来说为什么如此重要?)
4:在和 NSOperationQueue 组合使用时,不用再通过 start 进行开启;
5:NSInvocationOperation 的使用一定要结合着 NSOperationQueue
代码展示:
NSInvocationOperation *InvocationOperationA = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run_invocationOperation) object:nil];InvocationOperationA.name = @"operation - invocationA";NSInvocationOperation *InvocationOperationB = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run_invocationOperation) object:nil];InvocationOperationB.name = @"operation - invocationB";NSInvocationOperation *InvocationOperationC = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run_invocationOperation) object:nil];InvocationOperationC.name = @"operation - invocationC";NSInvocationOperation *InvocationOperationD = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run_invocationOperation) object:nil];InvocationOperationD.name = @"operation - invocationD";NSInvocationOperation *InvocationOperationE = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run_invocationOperation) object:nil];InvocationOperationE.name = @"operation - invocationE";//启动任务 :NSInvocationOperation 在和 NSOperationQueue 组合使用时,不需要使用 start// [InvocationOperationA start];// [InvocationOperationB start];// [InvocationOperationC start];// [InvocationOperationD start];//NSOperationQueue - 线程队列NSOperationQueue *operQueue = [[NSOperationQueue alloc] init];operQueue.name = @"oper_Queue"; //设置队列名称[operQueue setMaxConcurrentOperationCount:2]; //设置队列中允许的最大线程并发数//判断任务的执行状态if (InvocationOperationA.isExecuting) { NSLog(@"InvocationOperationA 是执行");}else{ NSLog(@"InvocationOperationA 还未执行");}/* NSOperationQueue - 两种在队列中添加事务的方式; 1 : addOperation 2 : addOperationWithBlock *///在队列中添加要执行的操作或者任务;[operQueue addOperation:InvocationOperationA];[operQueue addOperation:InvocationOperationB];[operQueue addOperation:InvocationOperationC];[operQueue addOperation:InvocationOperationD];[operQueue addOperation:InvocationOperationE];
###2:NSBlockOperation
NSBlockOperation 两种方式存放任务代码
1:类方法 - blockOperationWithBlock
* 2:实例方法 - addExecutionBlock*
注意事项:
1:单独使用 NSBlockOperation 设置一个 addExecutionBlock 不会开启新线程,会在主线程中执行,造成主线程堵塞;
2:单独使用 NSBlockOperation 中的 addExecutionBlock 方式设置任务时候,任务除在主线程执行之外,还会开启新的子线程来执行其他任务。但还是会造成主线程的堵塞;
3:创建 NSBlockOperation 对象之后需要手动开启 start ;
4:此时要结合 NSOperationQueue 组合使用;(衍生出一个问题:GCD , operation 都体现出了线程队列的概念,队列对多线程来说为什么如此重要?)
5:在和 NSOperationQueue 组合使用时,不用再通过 start 进行开启;
实现组合两种: 都不会主线程的堵塞
第一种 :
1 :NSBlockOperation 实例化一个对象;
2 :使用 addExecutionBlock 添加要执行的任务代码;可以添加多个;
3 :创建 NSOperationQueue 实例
4 :在 NSOperationQueue 实例中添加 NSBlockOperation 实例
5 :不要再使用 start 进行启动了
优缺点:
(优点)1:不用创建很多 NSBlockOperation 对象,在一个对象添加多个任务的 block 代码;
(优点)2:会根据 NSBlockOperation 中添加的 block 块数量开启相应多的子线程执行任务;(需要思考的问题:为什么会根据 block 开启子线程?是不是和 block 的实现原理有关,或者和其特殊属性有关?)
(缺点)3:通过 NSOperationQueue 的函数 setMaxConcurrentOperationCount 控制并发数是不生效的;
第二种 :
1 :NSBlockOperation 实例化多个对象;
2 :在每个 NSBlockOperation 实例对象中设置任务的 block 代码;
3 :创建 NSOperationQueue 实例
4 :在 NSOperationQueue 实例中添加所有要使用的 NSBlockOperation 实例
5 :不要再使用 start 进行启动了
优缺点:
(优点)1:可以通过 NSOperationQueue 的函数 setMaxConcurrentOperationCount 控制并发数;
(优点)2:会根据 NSBlockOperation 的 setMaxConcurrentOperationCount 设置数量开启相应多的子线程执行任务;
(缺点)3:需要为每一个任务的 block 块创建一个 NSBlockOperation 实例;
代码展示:
[NSBlockOperation blockOperationWithBlock:^{ for (int i = 0; i <= 10 ; i ++) { sleep(1); NSLog(@"类方法 blockOperation - 当前线程名称:%@ ——%d",[NSThread currentThread].name,i); }}];NSBlockOperation *blockOperation = [[NSBlockOperation alloc] init];blockOperation.name = @"blockOperation";[blockOperation addExecutionBlock:^{ for (int i = 0; i <= 10 ; i ++) { sleep(1); NSLog(@"blockOperation - 当前线程名称:%@ ——%d",[NSThread currentThread].name,i); }}];[blockOperation addExecutionBlock:^{ for (int i = 20; i <= 30 ; i ++) { sleep(1); NSLog(@"blockOperation - 当前线程名称:%@ ——%d",[NSThread currentThread].name,i); }}];[blockOperation addExecutionBlock:^{ for (int i = 30; i <= 40 ; i ++) { sleep(1); NSLog(@"blockOperation - 当前线程名称:%@ ——%d",[NSThread currentThread].name,i); }}];// [blockOperation start];NSBlockOperation *blockOperationA = [[NSBlockOperation alloc] init];blockOperationA.name = @"blockOperationA";[blockOperationA addExecutionBlock:^{ for (int i = 0; i <= 10 ; i ++) { sleep(1); NSLog(@"blockOperationA - 当前线程名称:%@ ——%d",[NSThread currentThread].name,i); }}];NSBlockOperation *blockOperationB = [[NSBlockOperation alloc] init];blockOperationB.name = @"blockOperationB";[blockOperationB addExecutionBlock:^{ for (int i = 0; i <= 10 ; i ++) { sleep(1); NSLog(@"blockOperationB - 当前线程名称:%@ ——%d",[NSThread currentThread].name,i); }}];NSBlockOperation *blockOperationC = [[NSBlockOperation alloc] init];blockOperationC.name = @"blockOperationC";[blockOperationC addExecutionBlock:^{ for (int i = 0; i <= 10 ; i ++) { sleep(1); NSLog(@"blockOperationC - 当前线程名称:%@ ——%d",[NSThread currentThread].name,i); }}];NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];[operationQueue setMaxConcurrentOperationCount:2];//方式一[operationQueue addOperation:blockOperation];//方式二// [operationQueue addOperation:blockOperationA];// [operationQueue addOperation:blockOperationB];// [operationQueue addOperation:blockOperationC];
3:创建子类继承自 NSOperation
//NSOperation - 自定义线程 - CustomOperation
*
个人解读:
所谓的自定义线程就是在继承 NSOperation 之后,在类内部设置好该类要执行的特定任务,也就是说自定线程,自定义的部分就是明确该线程要执行的操作是什么。
*
1:创建文件
2:在.m文件重写 main 方法
- (void) main {//NSOperation - 自定义使用实现子线程操作 - 同步任务NSLog(@"线程名字 = %@",self.name);for (int i = 0; i <= 10 ; i ++) { sleep(1); NSLog(@"自定义线程 %@——%d",self.name,i);}}
3:如果在自定义 NSOperation 时 自定义使用实现子线程操作 - 异步任务,
NSLog(@"开始任务");dispatch_async(dispatch_get_global_queue(0, 0), ^{ if (self.isCancelled) { return ; } for (int i = 0; i <= 10 ; i ++) { sleep(1); NSLog(@"自定义线程 ——%d",i); } NSLog(@"循环结束"); self.over = YES;});NSLog(@"结束任务");
执行结果:
该如何解决:
NSLog(@"开始任务");dispatch_async(dispatch_get_global_queue(0, 0), ^{ if (self.isCancelled) { return ; } for (int i = 0; i <= 10 ; i ++) { sleep(1); NSLog(@"自定义线程 ——%d",i); } NSLog(@"循环结束"); self.over = YES;});//解决办法 : 使用 NSRunLoop 进行循环执行/* 通过 NSRunLoop 的控制线程,等待异步任务完成之后再让该线程执行完成。 */while (!self.over && !self.isCancelled) { [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];}NSLog(@"结束任务");
NSOperation有一个很大的便捷就是处理线程依赖:
CustomOperation *operation1 = [[CustomOperation alloc] initWithName:@"自定义线程一"];CustomOperation *operation2 = [[CustomOperation alloc] initWithName:@"自定义线程二"];CustomOperation *operation3 = [[CustomOperation alloc] initWithName:@"自定义线程三"];CustomOperation *operation4 = [[CustomOperation alloc] initWithName:@"自定义线程四"];CustomOperation *operation5 = [[CustomOperation alloc] initWithName:@"自定义线程五"];NSOperationQueue *queue = [[NSOperationQueue alloc] init];queue.name = @"自定义线程的所在队列";[queue setMaxConcurrentOperationCount:2];//NSOperation - 线程依赖 Dependency(依赖)/* 添加上依赖之后,两个线程就有了依赖关系,举例说明, A 设置了依赖 B ,带代码执行阶段时, 只有当 B 执行完之后才会执行 A; 应用场景: 在实际开发过程中,任务3 之后再任务1和任务2完成之后才能执行就可以使用依赖关系 注意事项: 再设置依赖关系的时候要注意不要添加依赖关系形成闭环,出现互相依赖的情况,会导致程序不执行; */[operation1 addDependency:operation5];[operation5 addDependency:operation2];[operation2 addDependency:operation4];[operation4 addDependency:operation3];// [operation3 addDependency:operation1]; 这一点一定要注意,千万要捋顺彼此的依赖关系//一对多的依赖关系/* 只有当多个有依赖的任务执行完成之后才会执行 */// [operation1 addDependency:operation5];// [operation1 addDependency:operation2];// [operation2 addDependency:operation4];// [operation4 addDependency:operation3];[queue addOperation:operation1];[queue addOperation:operation2];[queue addOperation:operation3];[queue addOperation:operation4];[queue addOperation:operation5];
- iOS
- iOS
- IOS
- iOS
- iOS
- IOS
- ios
- iOS
- iOS
- IOS
- iOS
- ios
- ios ~~~~~
- ios
- IOS
- IOS
- IOS
- ios
- 华为OJ训练之0039-170114-合法IP
- MatchNet: Unifying Feature and Metric Learning for Patch-Based Matching
- 通过注册表修改IE的Internet选项
- ubuntu安装nginx及配置nginx
- 安卓通过自定义view实现水波进度条控件
- ios
- Problem A: 你会定义类吗?
- 剑指offer:第5题从尾到头打印链表
- Python list clear
- 云安全之Neutron 是如何实现虚机防火墙的 [How Neutron Implements Security Group]
- 国务院关于做好省级以下国土资源管理体制改革有关问题的通知-国发(2004)12号
- Notes on NNDL(Neural Networks and Deep Learning)
- [Leetcode] 11. Container With Most Water
- 求三位数相乘的最大回文数?