iOS多线程编程之NSOperation和NSOperationQueue的使用

本文介绍了NSOperation的两种使用方式:NSInvocationOperation和NSBlockOperation,以及通过继承NSOperation来自定义操作。文章还详细讲解了如何控制线程池中的线程数量,并对比了NSOperationQueue与GCD的优点。

著作权声明:本文由http://blog.youkuaiyun.com/totogo2010/原创

使用 NSOperation的方式有两种,

一种是用定义好的两个子类:

NSInvocationOperation 和 NSBlockOperation。

另一种是继承NSOperation

如果你也熟悉Java,NSOperation就和java.lang.Runnable接口很相似。和Java的Runnable一样,NSOperation也是设计用来扩展的,只需继承重写NSOperation的一个方法main。相当与java 中Runnalbe的Run方法。然后把NSOperation子类的对象放入NSOperationQueue队列中,该队列就会启动并开始处理它。


NSInvocationOperation例子:

和前面一篇博文一样,我们实现一个下载图片的例子。新建一个Single View app,拖放一个ImageView控件到xib界面。

实现代码如下:

#import "ViewController.h"
#define kURL @"http://avatar.youkuaiyun.com/2/C/D/1_totogo2010.jpg"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    NSInvocationOperation *operation = [[NSInvocationOperation alloc]initWithTarget:self
                                                                           selector:@selector(downloadImage:)
                                                                             object:kURL];
    
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    [queue addOperation:operation];
	// Do any additional setup after loading the view, typically from a nib.
}

-(void)downloadImage:(NSString *)url{
    NSLog(@"url:%@", url);
    NSURL *nsUrl = [NSURL URLWithString:url];
    NSData *data = [[NSData alloc]initWithContentsOfURL:nsUrl];
    UIImage * image = [[UIImage alloc]initWithData:data];
    [self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES];
}
-(void)updateUI:(UIImage*) image{
    self.imageView.image = image;
}

  1. viewDidLoad方法里可以看到我们用NSInvocationOperation建了一个后台线程,并且放到NSOperationQueue中。后台线程执行downloadImage方法。
  2. downloadImage 方法处理下载图片的逻辑。下载完成后用performSelectorOnMainThread执行主线程updateUI方法。
  3. updateUI 并把下载的图片显示到图片控件中。

第二种方式继承NSOperation 

在.m文件中实现main方法,main方法编写要执行的代码即可。

如何控制线程池中的线程数?

队列里可以加入很多个NSOperation, 可以把NSOperationQueue看作一个线程池,可往线程池中添加操作(NSOperation)到队列中。线程池中的线程可看作消费者,从队列中取走操作,并执行它。

通过下面的代码设置:
[queue setMaxConcurrentOperationCount:5];
线程池中的线程数,也就是并发操作数。默认情况下是-1,-1表示没有限制,这样会同时运行队列中的全部的操作。

@interface YourOperation : NSOperation
@end

@implementation YourOperation
- (void)main{
     // 任务代码
     ...
}
@end

@implementation YourOperation
- (void)start
{
    self.isExecuting = YES;
    // 任务代码 ...
}
- (void)finish //异步回调
{
    self.isExecuting = NO;
    self.isFinished = YES;
}
@end

1. 使用 main方法非常简单,开发者不需要管理一些状态属性(例如 isExecuting 和 isFinished),当 main 方法返回的时候,这个 operation 就结束了。这种方式使用起来非常简单,但是灵活性相对重写 start 来说要少一些, 因为main方法执行完就认为operation结束了,所以一般可以用来执行同步任务。

2. 如果你希望拥有更多的控制权,或者想在一个操作中可以执行异步任务,那么就重写 start方法, 但是注意:这种情况下,你必须手动管理操作的状态, 只有当发送 isFinished的 KVO 消息时,才认为是 operation 结束。

当实现了start方法时,默认会执行start方法,而不执行main方法。为了让操作队列能够捕获到操作的改变,需要将状态的属性以配合 KVO的方式进行实现。如果你不使用它们默认的 setter 来进行设置的话你就需要在合适的时候发送合适的 KVO消息。

需要手动管理的状态有:

    isExecuting
    代表任务正在执行中
    isFinished
    代表任务已经执行完成
    isCancelled
    代表任务已经取消执行
    手动的发送 KVO消息, 通知状态更改如下 :

[self willChangeValueForKey:@"isCancelled"];
_isCancelled = YES;
[self didChangeValueForKey:@"isCancelled"];

为了能使用操作队列所提供的取消功能,你需要在长时间操作中时不时地检查 isCancelled属性, 比如在一个长的循环中:

@implementation MyOperation

- (void)main
{
    while (notDone && !self.isCancelled) {
        // 任务处理
    }
}
@end

NSOperationQueue相对于GCD来说有以下优点:

  • 提供了在 GCD 中不那么容易复制的有用特性。
  • 可以很方便的取消一个NSOperation的执行
  • 可以更容易的添加任务的依赖关系
  • 提供了任务的状态:isExecuteing, isFinished.
具有多种最大功率点跟踪(MPPT)方法的光伏发电系统(P&O-增量法-人工神经网络-模糊逻辑控制-粒子群优化)之使用粒子群算法的最大功率点追踪(MPPT)(Simulink仿真实现)内容概要:本文介绍了一个涵盖多个科研领域的综合性MATLAB仿真资源集合,重点聚焦于光伏发电系统中基于粒子群优化(PSO)算法的最大功率点追踪(MPPT)技术的Simulink仿真实现。文档还列举了多种MPPT方法(如P&O、增量电导法、神经网络、模糊逻辑控制等),并展示了该团队在电力系统、智能优化算法、机器学习、路径规划、无人机控制、信号处理等多个方向的技术服务能力与代码实现案例。整体内容以科研仿真为核心,提供大量可复现的Matlab/Simulink模型优化算法应用实例。; 适合人群:具备一定电力电子、自动控制或新能源背景,熟悉MATLAB/Simulink环境,从事科研或工程仿真的研究生、科研人员及技术人员。; 使用场景及目标:①学习并实现光伏系统中基于粒子群算法的MPPT控制策略;②掌握多种智能优化算法在电力系统与自动化领域的建模与仿真方法;③获取可用于论文复现、项目开发技术攻关的高质量仿真资源。; 阅读建议:建议结合提供的网盘资料,按照研究方向选取对应模块进行实践,重点关注Simulink模型结构与算法代码逻辑的结合,注重从原理到仿真实现的全过程理解,提升科研建模能力。
热成像人物检测数据集 一、基础信息 数据集名称:热成像人物检测数据集 图片数量: 训练集:424张图片 验证集:121张图片 测试集:61张图片 总计:606张热成像图片 分类类别: - 热成像人物:在热成像图像中的人物实例 - 非热成像人物:在非热成像或普通图像中的人物实例,用于对比分析 标注格式: YOLO格式,包含边界框类别标签,适用于目标检测任务。数据来源于热成像视觉图像,覆盖多种场景条件。 二、适用场景 热成像监控与安防系统开发: 数据集支持目标检测任务,帮助构建能够在低光、夜间或恶劣环境下自动检测定位人物的AI模型,提升监控系统的可靠性实时响应能力。 红外视觉应用研发: 集成至红外摄像头或热成像设备中,实现实时人物检测功能,应用于安防、军事、救援工业检测等领域。 学术研究与创新: 支持计算机视觉与热成像技术的交叉研究,助力开发新算法用于人物行为分析或环境适应型检测模型。 教育与培训: 可用于高校或培训机构,作为学习热成像人物检测AI模型开发的教学资源,提升实践技能。 三、数据集优势 精准标注与多样性: 每张图片均由专业标注员标注,确保边界框定位准确,类别分类清晰。包含热成像非热成像类别,提供对比数据,增强模型的泛化能力鲁棒性。 场景实用性强: 数据覆盖多种环境条件,如不同光照天气,模拟真实世界应用,适用于复杂场景下的人物检测任务。 任务适配性高: YOLO标注格式兼容主流深度学习框架(如YOLOv5、YOLOv8等),可直接加载使用,支持快速模型开发评估。 应用价值突出: 专注于热成像人物检测,在安防、监控特殊环境检测中具有重要价值,支持早期预警高效决策。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值