多线程工具之NSOperationQueue

本文深入讲解了NSOperationQueue的工作原理及应用,包括NSOperation的基本概念、子类创建、依赖关系处理、队列最大并发数设置等内容,并介绍了如何通过NSOperationQueue进行高效的多线程编程。
优点:
        使用NSOperationQueue方式进行多线程编程,不能够像NSThread一样直接管理线程(是看不见线程的),也不需要管理,但是可以间接的干预线程。
 
1.NSOperation
           是一个抽象类,用来封装单任务的代码和数据
抽象类,所以不能直接使用该类,而是创建子类或者一些系统定义的子类 (NSInvocationOperation 或者 NSBlockOperation)来完成实际的任务。
 
2.NSOperation子类的创建
 
//子类CNOperation的创建继承NSOperation
    CNOperation* op = [[CNOperation alloc]init];
//NSOperation默认并不会执行,必须调用start方法
    [op start];
 
 
#import "CNOperation.h"

@implementation CNOperation
- (void)main{
 
    NSLog(@"do something");
}
@end
 
3.系统自带的NSOperation子类
(NSInvocationOperation 或者 NSBlockOperation)
 
1.创建NSInvocationOperation
    NSInvocationOperation* iop = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(invoAction) object:nil];
    [iop start];
   
 
 
2.创建NSBlockOperation
    1.系统block    
    NSBlockOperation* bop = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"do other something");
    }];
    [bop start];
 
    2.自定义block
//在CNOperation类中自己写block也可以
@property(copy)void(^block)(void);
 
//在CNOperation类中的main方法中调用block
- (void)main{
    //调用block
    if (_block) {
        _block();
    }
 
 CNOperation* cn = [[CNOperation alloc]init];
    //block实现
    [cn setBlock:^{
        NSLog(@"do something");
        //死循环
       // while(true){
//
       // }
    }];
    [cn start];
         // NSLog(@“因为有死循环,所以该语句永远不会被打印出来”);
小结:
       NSOperation默认并不会执行,必须调用start方法,执行时默认在当前线程中执行,即 默认同步执行。
 
什么实同步执行呢?
        就是block执行不完,start就不会执行
怎样调用的呢?
        比如在上面的代码中,默认程序先走到start,start又调用的main,main又调用的block ,层层调用,后调用的先执行,所以block先执行start后执行,先打印do something 
4.NSOperationQueue
 
一个NSOperationQueue对象并非一个线程,而是线程管理器,可以帮我们自动创建新的线 程。
取决于队列的最大并行数。NSOperation对象添加到队列中,默认就成为了异步执行(非 当前线程)。
 
1.解释同步执行和异步执行,演示Queue是怎样实现的异步执行
CNOperation* cn = [[CNOperation alloc]init];
    //block实现
    [cn setBlock:^{
        NSLog(@"do something");
        //死循环
        while (true) {
           
        }
    }];
    //同步执行(在当前线程执行op任务),该start永远不会被执行,因为block中有死循环,block执行不完,start不会被执行
//    [cn start];
    //异步执行(在其他线程执行op任务), 该start不会被执行,后面的代码会被打印,因为异步执行是不管block执不执行完,start都会执行
         //异步执行只需要将start方法放到新的线程中调用,该performSelectorInBackground是隐式创建的线程,我们都没有办法管理他,所以我们用queue来创建新的线程,这就是新学的内容
    [cn performSelectorInBackground:@selector(start) withObject:nil];
    NSLog(@"aaa");
5.创建NSOperationQueue
 
1.创建NSOperationQueue
 
  //创建线程管理器
    NSOperationQueue* opQ = [[NSOperationQueue alloc]init];
   
 
2.添加单个operation到queue中
 
NSBlockOperation* bop1 = [NSBlockOperation blockOperationWithBlock:^{
       
        NSLog(@"bop1......");
        NSLog(@"bop1:%@",[NSThread currentThread]);
//        usleep(1000000);
 
    }];
    //添加到queue后,不需要手动start,会自动开始执行
//    [bop1 start];
   
   
    NSBlockOperation* bop2 = [NSBlockOperation blockOperationWithBlock:^{
       
        NSLog(@"bop2.......");
        NSLog(@"bop2:%@",[NSThread currentThread]);
//        usleep(1000000);


    }];
//    [bop2 start];
   
    //添加到Queue中的NSOperation会自动执行,执行的时间取决于两个因素一个是依赖。一个是优先级
//    [opQ addOperation:bop1];
//    [opQ addOperation:bop2];
3.可以同时添加多个OperationQueue
 
//可以同时添加多个Operation到Queue中
    //waitUntilFinished设置为NO就是不用等待queue全部执行完就可以执行后面的语句--ok---
    //waitUntilFinished设置为YES就是等待queue全部执行完后才可以执行后面的语句
    [opQ addOperations:@[bop1,bop2] waitUntilFinished:YES];
    NSLog(@"-----OK-----");
 
 
4.队列的最大并发数
 
    //设置队列的最大并发数
    //最大并行数为1时,所有的op都会串行,并不代表只有一个线程1-1-2-2
    opQ.maxConcurrentOperationCount = 1;
/ / 若不设置最大并发书打印的operation可能会交替出现2-1-2-1
5. 可以隐式的添加一个OperationQueue
 
意思是不需要自己创建一个operation,而是让queue自己创建
[opQ addOperationWithBlock:^{
        NSLog(@"可以隐式的添加一个Operation到Queue中");
        NSLog(@"keyi:%@",[NSThread currentThread]);
 
//        usleep(1000000);
    }];
6.添加NSOperation的依赖对象
 
注意:
NSOperation添加到queue之后,绝对不要再修改NSOperation对象的状态,因为此时的operation可能会在任何时候运行,因此只能查看NSOperation对象的状态,比如是否正在运行,等待运行,已经完成等。
 
6.1添加依赖
添加依赖成功的前提是必须将operation添加到queue中,因为自动执行才有可能产生依赖关系
 
 
 NSOperationQueue *queue = [[NSOperationQueue alloc] init];
   
    NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^()
                                    {
                                        NSLog(@"执⾏行第1次操作,1:%@", [NSThread currentThread]);
                                    }];
    NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^()
                                    {
                                        NSLog(@"执⾏行第2次操作,2:%@", [NSThread currentThread]);
                                    }];
    NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^()
                                    {
                                        NSLog(@"执⾏行第3次操作,3:%@", [NSThread currentThread]);
                                    }];
    
    //添加依赖
    //依赖关系会影响到NSOperation对象在queue中的执行顺序
    //添加依赖成功的前提,必须将Operation添加到Queue中
         / / 添加依赖后默认会在同一个线程中执行,不完全对
    [operation1 addDependency:operation2];
    [operation1 addDependency:operation3];
   
    //添加多个依赖后,上边的话就不对,而应该改operation1会在最后执行的依赖operation执行的线程中执行 
    //意思是op2依赖于op1所以op2先执行,而op3依赖于op1所以op3先执行,那么op2和op3谁先执行呢?op3和op2不一定谁先执行,op1会在依赖的最后一个线程中执行,因为当前打印中op2最后执行,所以op1和op2是在同一个线程
 
   //设置优先级
    //首先根据依赖关系,确定前后执行顺序,其次在满足依赖关系的前提下,再根据优先级排序。
    operation2.qualityOfService = NSQualityOfServiceUserInteractive;
    operation3.qualityOfService = NSQualityOfServiceBackground;
//
    
//    //注意:不能创建环形依赖,比如A依赖B,B依赖A,这是错误的,
//    [operation2 addDependency:operation1];
   //op2执行不完op1不能执行,op1执行不完op2不能执行
  //添加到queue之前添加依赖
    //打印出来的执行顺序不确定
    //添加到queue中的operation不应该再去修改属性
    [queue addOperation:operation1];
    [queue addOperation:operation2];
    [queue addOperation:operation3];
7. NSOperationQueue的取消,等待, 暂停和继续queue
 
NSOperationQueue* queue = [[NSOperationQueue alloc]init];
   
    NSBlockOperation* op1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"block opreation1");
        NSLog(@"1:%@",[NSThread currentThread]);
    }];
   
    NSBlockOperation* op2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"block opreation2");
        NSLog(@"2:%@",[NSThread currentThread]);
       
        //取消op1 必须在op1执行前取消,否者无效
//        [op1 cancel];
     
        //暂停,,不是operation暂停和继续,任务开始后无法暂停取消,而是queue暂停和取消,暂停queue,不会暂停当前正在执行的operation,而是一直执行完,暂停只是会停止开启新的在等待的operation
//        [queue setSuspended:YES];
        //因为operation2正在执行,所以不会被暂停,而operation1被暂停
       
    }];
 
   
    //没添加依赖前,op开始执行后无法取消,仍然把op1和op2都执行出来
         / /但是添加依赖后就不一样了,添加依赖后op2先执行,此时op1还没有执行,这是就可以取消op1了
    [op1 addDependency:op2];
   
    [queue addOperation:op1];
    [queue addOperation:op2];
    
    //取消queue中的所有的操作
//     [queue cancelAllOperations];
   
    //等待卡死当前线程
    //等待op2执行完毕后,再执行
//    [op2 waitUntilFinished];
    //等待queue所有操作执行完毕后执行
    [queue waitUntilAllOperationsAreFinished];
    NSLog(@"..........");
   
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        //延时3秒后继续queue
        [queue setSuspended:NO];
    });

转载于:https://www.cnblogs.com/gaominmin/p/4821511.html

标题基于Python的自主学习系统后端设计与实现AI更换标题第1章引言介绍自主学习系统的研究背景、意义、现状以及本文的研究方法和创新点。1.1研究背景与意义阐述自主学习系统在教育技术领域的重要性和应用价值。1.2国内外研究现状分析国内外在自主学习系统后端技术方面的研究进展。1.3研究方法与创新点概述本文采用Python技术栈的设计方法和系统创新点。第2章相关理论与技术总结自主学习系统后端开发的相关理论和技术基础。2.1自主学习系统理论阐述自主学习系统的定义、特征和理论基础。2.2Python后端技术栈介绍DjangoFlask等Python后端框架及其适用场景。2.3数据库技术讨论关系型和非关系型数据库在系统中的应用方案。第3章系统设计与实现详细介绍自主学习系统后端的设计方案和实现过程。3.1系统架构设计提出基于微服务的系统架构设计方案。3.2核心模块设计详细说明用户管理、学习资源管理、进度跟踪等核心模块设计。3.3关键技术实现阐述个性化推荐算法、学习行为分析等关键技术的实现。第4章系统测试与评估对系统进行功能测试和性能评估。4.1测试环境与方法介绍测试环境配置和采用的测试方法。4.2功能测试结果展示各功能模块的测试结果和问题修复情况。4.3性能评估分析分析系统在高并发等场景下的性能表现。第5章结论与展望总结研究成果并提出未来改进方向。5.1研究结论概括系统设计的主要成果和技术创新。5.2未来展望指出系统局限性并提出后续优化方向。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值