当前位置: 首页 > wzjs >正文

网站运营发展前景南昌seo排名外包

网站运营发展前景,南昌seo排名外包,上海房价2022年最新房价,wordpress vip购买页面iOS NSOperation 和 NSOperationQueue 文章目录 iOS NSOperation 和 NSOperationQueue前言NSOperation简介使用步骤基本使用:创建NSOperation创建NSOperationQueue操作加入队列 NSOperationQueue控制串行执行,并发执行NSOperation操作依赖NSOpeation优先级 线程安全 小结 前言 …

iOS NSOperation 和 NSOperationQueue

文章目录

  • iOS NSOperation 和 NSOperationQueue
    • 前言
      • NSOperation简介
      • 使用步骤
        • 基本使用:
          • 创建NSOperation
          • 创建NSOperationQueue
          • 操作加入队列
        • NSOperationQueue控制串行执行,并发执行
        • NSOperation操作依赖
        • NSOpeation优先级
      • 线程安全
    • 小结

前言

前段时间学习了有关于GCD的内容,这段时间对于NSOperation的内容再进行一个学习和总结

NSOperation简介

实际上 NSOperationNSOperationQueue 是基于 GCD 更高一层的封装,完全面向对象。但是比 GCD 更简单易用、代码可读性也更高。

NSOperation需要配合NSOperationQueue来实现多线程。

  • 操作的定义:
    • 执行操作的含义,换句话说其实就是在线程中执行的那段代码,从GCD层面来类比就相当于我们的一个block
    • NSOperation中,我们可以采用他的子类来进行一个封装的操作
  • 操作队列:
    • 这里的队列是值操作队列,就是用来存放操作的队列.不同于GCD中的一个调度队列的FIFO的原则.NSOperation对于添加到队列中的操作,首先进入准备就绪的状态,然后进入就绪状态的操作的开始执行顺序有操作之间的优先级来决定.
    • 操作队列通过设置最大并发操作数来控制并发.串行
    • NSOperationQueue为我们提供了两种不同类型的队列:主队列和自定义队列.主队列运行在主线程上,自定义队列在后台运行

使用步骤

这里我们使用NSOperation的步骤主要分成三步

  • 创建操作:先将需要执行的操作粉装到一个NSOperation对象中
  • 创建队列:创建一个NSOperationQueue对象
  • 将操作加入队列中:将NSOperation对象添加到NSOperationQueue
基本使用:
创建NSOperation
  1. 使用子类NSInvocationOperation
  2. 使用子类NSBlockOperation
  3. 自定义继承于NSOperation的子类,通过实现内部对应的方法来实现封装操作

这里我们先采用第一种方式来处理:

- (void)useInvocationOperation {NSInvocationOperation* operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(task1) object:nil]; // 创建NSInvocationOperation这个对象[operation start];
}
- (void)task1 {for (int i = 0; i < 2; i++) {[NSThread sleepForTimeInterval:2]; // 模拟耗时操作NSLog(@"%ld -----%@", i, [NSThread currentThread]); // 打印对应任务和线程的信息}
}

image-20250605200651986

  • 结合上面的图片我们可以看出在主线程中单独使用NSInvocationOperation的话,操作是在当前线程执行的,并没有开启新线程
  • 如果在其他线程中运行就会打印对应的一个线程的信息:[NSThread detachNewThreadSelector:@selector(useInvocationOperation) toTarget:self withObject:nil];

image-20250605201617788

这里并不可以开启一个新线程:

  • 现在采用第二种方式NSBlockOperation
- (void)useBlockOperation {NSBlockOperation* op = [NSBlockOperation blockOperationWithBlock:^{for (int i = 0; i < 2; i++) {[NSThread sleepForTimeInterval:2];NSLog(@"%ld----%@", i, [NSThread currentThread]);}}];[op start];
}

image-20250605202307074

  • 和上面一样在主线程调用之后发现它也没有一个开启新线程的能力,如果仅仅采用我们的NSOperation就没有开启新线程

这里我们如果我们采用下面这个方法addExecutionBlock:的话,可以在不同的线程中执行,实现一个并发执行:

- (void)useBlockOperation {NSBlockOperation* op = [NSBlockOperation blockOperationWithBlock:^{for (int i = 0; i < 2; i++) {[NSThread sleepForTimeInterval:2];NSLog(@"0----%@", [NSThread currentThread]);}}];[op addExecutionBlock:^{for (int i = 0; i < 2; i++) {[NSThread sleepForTimeInterval:2];NSLog(@"1----%@",  [NSThread currentThread]);}}];[op addExecutionBlock:^{for (int i = 0; i < 2; i++) {[NSThread sleepForTimeInterval:2];NSLog(@"2----%@", [NSThread currentThread]);}}];[op addExecutionBlock:^{for (int i = 0; i < 2; i++) {[NSThread sleepForTimeInterval:2];NSLog(@"3----%@", [NSThread currentThread]);}}];[op addExecutionBlock:^{for (int i = 0; i < 2; i++) {[NSThread sleepForTimeInterval:2];NSLog(@"4----%@", [NSThread currentThread]);}}];[op start];
}

image-20250605203237977

  • 这里可以看出使用子类NSBlockOperation并且调用方法AddExecutionBlock的情况下,blockOperaitonWithBlock:方法中的操作和addExecutionBlock:中的操作是在不同的线程中异步执行的,从而验证了blockOperationWithBlock中的操作也可能会在其他线程中执行

一般情况下,如果一个 NSBlockOperation 对象封装了多个操作。NSBlockOperation 是否开启新线程,取决于操作的个数。如果添加的操作的个数多,就会自动开启新线程。当然开启的线程数是由系统来决定的。

下面采用第三种方法:自定义NSOperation的子类

#import "NanxunOperation.h"@implementation NanxunOperation
- (void)main {if (!self.isCancelled) {for (int i = 0; i < 2; i++) {[NSThread sleepForTimeInterval:2];NSLog(@"1---%@", [NSThread currentThread]);}}
}
@end

image-20250605204139042

  • 可以看出:在没有使用NSOperationQueue,在主线程单独使用自定义继承NSOperation的子类情况下,是在主线程执行操作,并没有开启新线程
创建NSOperationQueue

NSOperationQueue一共有两种队列:主队列,自定义队列.自定义队列包含了串行,并发等多种功能

  • 主队列:
    • 但凡添加到主队列,都会放到主线程中执行
NSOperationQueue* queue = [NSOperationQueue mainQueue];
  • 自定义队列
    • 添加到这种队列中的操作,就会自动放到子线程中执行
    • 同时包含了:串行,并发等功能
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
操作加入队列
  1. -(void)addOperation:(NSOperation*) op:
    • 先创建操作,在讲创建好的操作加入到创建好的队列中
- (void)addOperationToQueue {NSOperationQueue* queue = [[NSOperationQueue alloc] init];NSInvocationOperation* op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(task1) object:nil];NSInvocationOperation* op2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(task1) object:nil];NSBlockOperation* op = [NSBlockOperation blockOperationWithBlock:^{for (int i = 0; i < 2; i++) {[NSThread sleepForTimeInterval:2];NSLog(@"3----%@", [NSThread currentThread]);}}];[op addExecutionBlock:^{for (int i = 0; i < 2; i++) {[NSThread sleepForTimeInterval:2];NSLog(@"4----%@", [NSThread currentThread]);}}];[queue addOperation:op];[queue addOperation:op1];[queue addOperation:op2];
}

image-20250605205410656

  • 这里可以看出通过NSOperation子类创建操作,并且使用addOperation:将操作加入到操作队列后能够开启新线程,进行一个并发执行
  1. - (void)addOperationWithBlock:(void (^)(void))block;
    • 无需先创建操作,在block中添加操作,直接将包含操作的block加入到队列中
- (void)addOperationWithBlockToQueue {NSOperationQueue* queue = [[NSOperationQueue alloc] init];[queue addOperationWithBlock:^{for (int i = 0; i < 2; i++) {[NSThread sleepForTimeInterval:2]; // 模拟耗时操作NSLog(@"1---%@", [NSThread currentThread]); // 打印当前线程}}];[queue addOperationWithBlock:^{for (int i = 0; i < 2; i++) {[NSThread sleepForTimeInterval:2]; // 模拟耗时操作NSLog(@"2---%@", [NSThread currentThread]); // 打印当前线程}}];[queue addOperationWithBlock:^{for (int i = 0; i < 2; i++) {[NSThread sleepForTimeInterval:2]; // 模拟耗时操作NSLog(@"3---%@", [NSThread currentThread]); // 打印当前线程}}];
}
  • 可以看出:使用addOperationWithBlock:将操作加入到操作队列后能够开启新线程,进行并发执行

image-20250605205830321

NSOperationQueue控制串行执行,并发执行

之前我们说过,NSOperationQueue创建的自定义队列同时具有串行,并发功能,上面我们演示了并发功能,怎么实现一个串行功能

这里有一个关键属性maxConcurrentOperationCount, 加做最大并发操作数,用来控制一个特定队列中有多少操作同时参与并发执行

注意:这里 maxConcurrentOperationCount 控制的不是并发线程的数量,而是一个队列中同时能并发执行的最大操作数。而且一个操作也并非只能在一个线程中运行

  • 最大并发操作数:maxConcurrentOperationCount
    • 默认情况下为-1,表示不进行一个限制,可进行并发执行
    • 值为1,此时队列为串行队列.只能串行执行
    • 大于1的时候.队列为并发队列,操作可并发执行,即使自己设置一个很大的值,系统也会自动调整为min
- (void)addOperationWithBlockToQueue {NSOperationQueue* queue = [[NSOperationQueue alloc] init];queue.maxConcurrentOperationCount = 1;[queue addOperationWithBlock:^{for (int i = 0; i < 2; i++) {[NSThread sleepForTimeInterval:2]; // 模拟耗时操作NSLog(@"1---%@", [NSThread currentThread]); // 打印当前线程}}];[queue addOperationWithBlock:^{for (int i = 0; i < 2; i++) {[NSThread sleepForTimeInterval:2]; // 模拟耗时操作NSLog(@"2---%@", [NSThread currentThread]); // 打印当前线程}}];[queue addOperationWithBlock:^{for (int i = 0; i < 2; i++) {[NSThread sleepForTimeInterval:2]; // 模拟耗时操作NSLog(@"3---%@", [NSThread currentThread]); // 打印当前线程}}];
}

image-20250605211748049

  • 可以看出最大并发数为1的时候,操作是按顺序串行执行的,并且一个操作完成之后,下一个操作才开始执行
  • 当如果设置最大并发操作为1的时候,操作是并发执行的,可以同时执行两个操作.而开启线程的数量是由系统决定的

image-20250605212004054

NSOperation操作依赖

我们可以通过添加操作依赖,让我们更加方便的控制操作之间的一个先后执行顺序:

  • - (void)addDependency:(NSOperation *)op; 添加依赖,使当前操作依赖于操作 op 的完成。
  • - (void)removeDependency:(NSOperation *)op; 移除依赖,取消当前操作对操作 op 的依赖。
  • @property (readonly, copy) NSArray<NSOperation *> *dependencies; 在当前操作开始执行之前完成执行的所有操作对象数组
- (void)addOperationToQueue {NSOperationQueue* queue = [[NSOperationQueue alloc] init];NSInvocationOperation* op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(task1) object:nil];NSInvocationOperation* op2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(task1) object:nil];NSBlockOperation* op = [NSBlockOperation blockOperationWithBlock:^{for (int i = 0; i < 2; i++) {[NSThread sleepForTimeInterval:2];NSLog(@"3----%@", [NSThread currentThread]);}}];[op addExecutionBlock:^{for (int i = 0; i < 2; i++) {[NSThread sleepForTimeInterval:2];NSLog(@"4----%@", [NSThread currentThread]);}}];[op addDependency:op1];[queue addOperation:op];[queue addOperation:op1];[queue addOperation:op2];
}

image-20250605212524248

这里通过添加依赖让结果都是op1先执行,op后执行

NSOpeation优先级

NSOperation给我们提供了一个优先级属性,queuePriority属性适用于同一操作队列中的操作,不使用不同操作队列的操作,

// 优先级的取值
typedef NS_ENUM(NSInteger, NSOperationQueuePriority) {NSOperationQueuePriorityVeryLow = -8L,NSOperationQueuePriorityLow = -4L,NSOperationQueuePriorityNormal = 0,NSOperationQueuePriorityHigh = 4,NSOperationQueuePriorityVeryHigh = 8
};

上边我们说过:对于添加到队列中的操作,首先进入准备就绪的状态(就绪状态取决于操作之间的依赖关系),然后进入就绪状态的操作的开始执行顺序(非结束执行顺序)由操作之间相对的优先级决定(优先级是操作对象自身的属性)。

  • 什么操作才可以被叫做进入就绪状态的操作

当一个操作的所有依赖都全部完成的时候,操作对象通常会进入准备就绪状态,等待执行

  • 这个属性决定了进入准备就绪状态下的操作之间的一个执行顺序
  • 如果一个队列中又有高优先级又有第优先级,并且两个操作都已经准备就绪,那么就先执行高优先级的操作
  • 如果一个队列中既有准备就绪状态的操作,有包含了未准备就绪的操作,但还是先执行准备就绪的操作,优先级不可移易取代依赖关系,如果要控制操作间的启动属性,就要采用依赖关系

线程安全

这里我们采用最经典的一个火车买票问题来对于线程安全进行一个分析:

- (void)initTickerStatueSave {NSLog(@"%@", [NSThread currentThread]);self.ticketCount = 50;self.lock = [[NSLock alloc] init];NSOperationQueue* que1 = [[NSOperationQueue alloc] init];que1.maxConcurrentOperationCount = 1;NSOperationQueue* que2 = [[NSOperationQueue alloc] init];que2.maxConcurrentOperationCount = 1;__weak typeof(self) weakSelf = self;NSBlockOperation* op1 = [NSBlockOperation blockOperationWithBlock:^{[weakSelf saleTicketSafe];}];NSBlockOperation* op2 = [NSBlockOperation blockOperationWithBlock:^{[weakSelf saleTicketSafe];}];[que1 addOperation:op1];[que1 addOperation:op2];
}
- (void)saleTicketSafe {while (1) {[self.lock lock];if (self.ticketCount > 0) {self.ticketCount--;NSLog(@"%@", [NSString stringWithFormat:@"%ld %@", self.ticketCount, [NSThread currentThread]]);[NSThread sleepForTimeInterval:0.2];}[self.lock unlock];if (self.ticketCount <= 0) {NSLog(@"所有火车票");break;}}
}

image-20250607151843008

通过上面的加锁就实现了一个线程安全.

小结

笔者学习了有关于NSOperation的一些基本用法,之后还会继续学习,如有缺失会继续补充相关内容

http://www.dtcms.com/wzjs/284679.html

相关文章:

  • 苹果手机做微电影网站有哪些互联网推广是什么工作内容
  • 网站开发的后端南京搜索引擎推广优化
  • 咨询类网站建设方案书自己怎么优化关键词
  • 小米商城网站开发文档网站免费网站免费优化优化
  • 北京朝阳区网站建设公司网站搭建公司哪家好
  • wordpress全站腾讯云cdn网络营销案例有哪些
  • 群晖可以做网站服务器吗体验营销策略有哪些
  • 网站怎么做?seo研究中心好客站
  • 免费开放的api网站应用北京关键词seo
  • 长治建设工程交易网seo百度点击软件
  • 松原市建设局网站海外推广是做什么的
  • 新闻网站数据库建设推广代理平台
  • 游戏开发物语破解版百度seo推广计划类型包含
  • wordpress做的外贸网站老司机们用的关键词有哪些
  • 南安淘宝网站建设个人友情链接推广
  • 怎么样做一个网站代刷网站推广链接免费
  • flash做的个人网站免费手机优化大师下载安装
  • 杭州网站公司线上营销推广方案模板
  • 江西省网站建设在线客服系统
  • 网站建设 博采网络网站外包公司有哪些
  • 南通网站建设要多少钱东莞网站建设排名
  • 微信公众号排名前十在线seo优化工具
  • 构建一个网站需要什么广告联盟app
  • 常德网站建设 天维徐州seo代理计费
  • wordpress 评论模板制作互联网seo是什么意思
  • 网站怎么做响应式网页广告怎么投放
  • 渭南市建网站深圳外包网络推广
  • 微信小程序游戏开发多少钱长春seo排名
  • 荆门哪里做网站如何自己编写网站
  • 网站网页设计入门百度手机网页版入口