NSOperation

NSOperation参考链接

NSOperation

继承自NSObject

NSInvocationOperation

直接在当前线程执行任务,不支持并发,因为初始化方法只支持执行一个任务,并且没有添加任务的方法。

- initWithTarget:selector:object:
- initWithInvocation:

NSBlockOperation

  1. 当任务加入队列时,会开辟新线程
  2. 当任务数等于1时,不会开辟新线程,在当前线程同步执行
  3. 当任务数大于1时会开辟新线程
  4. NSBlockOperation添加操作数大于1时,除第一个任务外,其任务就是异步执行

自定义子类

  1. 同步
    直接冲洗main方法就可以
    默认情况下,该operation在当前调用start的线程中执行.其实如果我们创建多个自定义的ZCNoCurrentOperation,并放入NSOperationQueue中,这些任务也是并发执行的,只不过因为我们没有处理并发情况下,线程执行完,KVO等操作,因此不建议在只实现main函数的情况下将其加入NSOperationQueue,只实现main一般只适合自定义非并发的。

  2. 异步
    start、asynchronous、executing、finished。并且需要自己创建自动释放池,因为异步操作无法访问主线程的自动释放池。
    原因:main方法的话,如果main方法执行完毕,那么整个operation就会从队列中被移除。如果你是一个自定义的operation并且它是某些类的代理,这些类恰好有异步方法,这是就会找不到代理导致程序出错了。然而start方法就算执行完毕,它的finish属性也不会变,因此你可以控制这个operation的生命周期了。然后在任务完成之后手动cancel掉这个operation即可。

注意点:If you provide custom implementations for any of the preceding properties, your implementations must maintain KVC and KVO compliance. If you define additional properties for your NSOperation objects, it is recommended that you make those properties KVC and KVO compliant as well.

NSOperationQueue

只要是创建了队列,在队列中的操作,就会在子线程中执行,并且默认并发操作。添加到子队列NSOperationQueue实例中的操作,都是异步执行
添加操作到NSOperationQueue中,自动执行操作,自动开启线程
从多个线程中使用一个NSOperationQueue对象是安全的,无需创建额外的锁来同步对该对象的访问。

suspended、cancel、cancelAllOperation

三者的共同点:如果任务已经在线程中执行,则不受此影响。
suspended:当NSOperationQueue对象属性suspended设置为YES,是队列停止了对任务调度。
一个操作执行还未完成时,我们可能需要让该任务暂停、可能之后在进行某些操作后又希望继续执行。影响的是加入队列,但未被调度到线程中正在执行的任务。如果任务已经在线程中执行,则不受此影响。
cancel cancelAllOperation:一旦调用了这2个方法,操作对象将无法恢复
只有队列标记为已经结束时才会从队列中移除,如果任务已经在线程中执行,则不受此影响。
对于队列中的操作,只有操作标记为已结束才能被队列移除。在队列中未被调度的操作,会调用start方法执行操作,以便操作对象处理取消事件。然后标记这些操作对象为已结束。对于正在线程中执行其任务的操作对象,正在执行的任务会继续执行,该操作对象会被标记经结束。

suspended、cancel、cancelAllOperation 注意:只会停止调度队列中操作对象,正在执行任务的依然会执行,且取消不可恢复。

依赖

操作添加到队列添加的顺序并不能决定执行顺序,执行的顺序取决于多种因素比如依赖、优先级等。

线程安全

NSOperation实例在多线程上执行是安全的,不需要添加额外的锁

等待操作

会阻塞当前线程

优先级

优先级只对当前队列有效。不同队列中的操作,低优先级有可能比高优先级先执行。优先级不能改变依赖关系

添加依赖和 waitUntilFinished 顺序错误会导致死循环

NSBlockOperation *blockOperation1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"1--%@",[NSThread currentThread]);
    }];
    NSBlockOperation *blockOperation2 = [NSBlockOperation blockOperationWithBlock:^{
        [blockOperation1 waitUntilFinished];
        NSLog(@"2--%@",[NSThread currentThread]);
    }];
    
    NSOperationQueue *queue1 = [[NSOperationQueue alloc] init];
    [blockOperation1 addDependency:blockOperation2];
    [queue1 addOperation:blockOperation2];
    [queue1 addOperation:blockOperation1];

解释:
首先在没有等待的时候你,队列的执行执行操作按照依赖顺序执行,如果没有依赖则按照添加到队列的顺序执行。
这里既有了等待,又又了依赖。此处,blockOperation2等待blockOperation1执行完成,然而blockOperation1又依赖于blockOperation2所以,死循环了。

自定义非并发

XSYOperation.h

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface XSYOperation : NSOperation

@end

XSYOperation.m

#import "XSYOperation.h"

@implementation XSYOperation

/*
 For non-concurrent operations, you typically override only one method:
 main
 */

- (void)main {
    
   @autoreleasepool {
       
       BOOL isDone = NO;
       while(![self isCancelled] && !isDone)
       {
           //在这里执行自己的任务操作
           NSLog(@"执行自定义非并发NSOperation");
           NSThread *thread = [NSThread currentThread];
           NSLog(@"%@",thread);
           //任务执行完成后将isDone设为YES
           isDone = YES;
       }
   }
}

@end

自定义并发

XSYConcurrentOperation.h

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface XSYConcurrentOperation : NSOperation {
    BOOL executing;
    BOOL finished;
}

@end

NS_ASSUME_NONNULL_END

XSYConcurrentOperation.m

#import "XSYConcurrentOperation.h"

/*
 If you are creating a concurrent operation, you need to override the following methods and properties at a minimum:
 start
 asynchronous
 executing
 finished
 */
@implementation XSYConcurrentOperation

- (instancetype)init {
    self = [super init];
    if (self) {
        executing = NO;
        finished = NO;
    }
    return self;
}

- (void)start {
    if ([self isCancelled]) {
        [self willChangeValueForKey:@"isFinished"];
        finished = YES;
        [self didChangeValueForKey:@"isFinished"];
        return;
    }
    //如果没被取消,开始执行任务
    [self willChangeValueForKey:@"isExecuting"];
    
    [NSThread detachNewThreadSelector:@selector(main) toTarget:self withObject:nil];
    executing = YES;
    [self didChangeValueForKey:@"isExecuting"];
}

- (BOOL)isConcurrent {
    return YES;
}

- (BOOL)isExecuting {
    return executing;
}

- (BOOL)isFinished {
    return finished;
}

- (void)main {
    @autoreleasepool {
        //任务执行完成后要实现相应的KVO
        [self willChangeValueForKey:@"isFinished"];
        [self willChangeValueForKey:@"isExecuting"];
        
        executing = NO;
        finished = YES;
        
        [self didChangeValueForKey:@"isExecuting"];
        [self didChangeValueForKey:@"isFinished"];
    }
}

@end

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,588评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,456评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,146评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,387评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,481评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,510评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,522评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,296评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,745评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,039评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,202评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,901评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,538评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,165评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,415评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,081评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,085评论 2 352

推荐阅读更多精彩内容