多线程NSOperation

NSOperation的作用:

配合使用NSOperation和NSOperationQueue能实现多线程编程.

NSOperation和NSOperationQueue能实现多线程的具体步骤

1.首先需要将执行的操作封装到一个NSOperation对象中(我们称之为 任务)
2.然后将NSOperation对象加到NSOperationQueue中
3.系统会自动将NSOperationQueue中的NSOperation取出来
4.将取出的NSOperation封装的操作放在一条新线程中执行

NSOperation的子类

1.NSOperation是一个抽象类,不具备封装操作的能力,必须使用它的子类
2.使用NSOperation子类的方式有3种
1>NSInvocationOperation
2>NSBlockOperation
自定义子类继承NSOperation,实现内部相应的方法

虽然NSOperation较GCD比较而言,有点繁琐,但是它能够自由的控制任务的执行,而且经过测试,它的稳定性比较高.

好了现在介绍:自定义NSOperation的方式来添加任务

自定义类,继承于NSOperation

// NSOperation内部有这个方法, 是用来专门,封装任务体的
// 默认情况下如果直接调用start的时候,不会新开一条新线程去执行操作
- (void)main
{
    [NSThread sleepForTimeInterval:1.0];
    NSLog(@"我爱你 ------ %@", [NSThread currentThread]);

}

利用NSInvocationOperation来添加任务

1.创建NSInvocationOperation对象

NSInvocationOperation *operation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(run:) object:@"我爱你"];

2.调用start方法开始执行操作

  • (void)start
    一点执行这个操作,就会调用target的sel的方法
    3.注意
    1>默认情况下,调用了start方法后并不会开一条新线程去执行操作,而是在当前线程同步执行操作
    2>只有将NSOperation放在一个NSOperationQueue中,才会异步执行操作

利用NSBlockOperation来添加任务

1.创建NSBlockOperation对象
2.通过addExecutionBlock:方法添加更多的操作
3.注意:只要NSBlockOperation封装的操作数 > 1,就会异步执行操作

// block 直接将 操作封装在 block中   ,执行的。  会进行并行操作,并且第一条操作  安排在主线程。 不必指定 target
    NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"ლ(′◉❥◉`ლ)----%@",[NSThread currentThread]);
    }];
    [operation addExecutionBlock:^{
        NSLog(@"我爱你----%@",[NSThread currentThread]);;
    }];
    [operation addExecutionBlock:^{
        NSLog(@"我爱你----%@",[NSThread currentThread]);;
    }];
    [operation addExecutionBlock:^{
        NSLog(@"我爱你----%@",[NSThread currentThread]);;
    }];
    // 调用  start 统一开始执行任务
    [operation start];

控制台输出:


Snip20150927_2.png

NSOperationQueue

NSOperationQueue的作用

1.NSOperation可以调用start方法来执行任务,但默认是同步执行的
2.如果将NSOperation添加到NSOperationQueue(操作队列)中,系统会自动异步执行NSOperation中的操作

添加操作(任务)到NSOperationQueue中 (需要注意的是,一旦加入队列,任务就会被执行.)

1.添加任务对象到队列中
- (void)addOperation:(NSOperation *)op
2.添加任务'block'到队列,直接执行
- (void)addOperationWithBlock:(void (^)(void))block

// 创建队列
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
//
__block UIImage *image1;
    NSBlockOperation *block1 = [NSBlockOperation blockOperationWithBlock:^{
        [NSThread sleepForTimeInterval:2.0];
        NSURL *url = [NSURL URLWithString:@"http://fc.topit.me/c/4f/99/11922014783d4994fco.jpg"]; 
        NSData *data = [NSData dataWithContentsOfURL:url];
        image1 = [UIImage imageWithData:data];
        NSLog(@"1------%@",[NSThread currentThread]);
        
    }];
    __block UIImage *image2;
    NSBlockOperation *block2 = [NSBlockOperation blockOperationWithBlock:^{
        [NSThread sleepForTimeInterval:2.0];
        NSURL *url = [NSURL URLWithString:@"http://cdn.duitang.com/uploads/item/201311/25/20131125164036_NUAC8.jpeg"];
        
        NSData *data = [NSData dataWithContentsOfURL:url];
        image2 = [UIImage imageWithData:data];
        NSLog(@"2------%@",[NSThread currentThread]);
    }];
    
    NSBlockOperation *block3 = [NSBlockOperation blockOperationWithBlock:^{
        UIGraphicsBeginImageContext(CGSizeMake(200, 200));
        
        [image1 drawInRect:CGRectMake(0, 50, 200, 150)];
        [image2 drawInRect:CGRectMake(0, 0, 200, 50)];
        
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
        
        UIGraphicsEndImageContext();
        
        // 回到主队列  , 进行UI赋值
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            self.imageView.image = image;
        }];
        
        
    }];
    
    // addDependency   添加依赖  ,  前俩个  ,执行完了之后  最后一个再执行。
    [block3 addDependency:block1];
    [block3 addDependency:block2];
    
    [queue addOperation:block1];
    [queue addOperation:block2];
    [  queue addOperation:block3 ];
    
    
    
//    // 先让执行 block1, block2 (异步并发执行) ,在进行  block3 的执行
//    [queue addOperations:@[block1,block2] waitUntilFinished:YES];
//    [queue addOperation:block3];
//    

几种常见的属性和方法

1.最大并发数(同时执行的任务数) 最大并发数一般都是系统给出,我任务,系统并发送是系统根据它的性能, 给分配的线程,如果性能高,可能多分点. 至于并发送内部怎么执行 ,系统自行做决定, 它认为哪条线程空闲,他就会把哪条线程交给你

- (NSInteger)maxCurrentOperationCount;
- (void)setMaxConcurrentOperationCount:(NSInteger)cnt

有些人,会陷入误区, 如果设置了最大并发数是1,那么系统就只会创建一条线程, 因为 同一时间只允许一条线程执行任务, 但是这种想法是错误的, 系统只是保持同一时间执行任务是一条线程, 但没表示 换个时间就不能换线程

// 默认不设置并发数的时候, 异步执行, 创建多条线程
let queue = NSOperationQueue()
        queue.addOperationWithBlock { () -> Void in
            print("1------\(NSThread.currentThread())")
        }
        queue.addOperationWithBlock { () -> Void in
            print("1------\(NSThread.currentThread())")
        }
        queue.addOperationWithBlock { () -> Void in
            print("1------\(NSThread.currentThread())")
        }
        queue.addOperationWithBlock { () -> Void in
            print("1------\(NSThread.currentThread())")
        }
        queue.addOperationWithBlock { () -> Void in
            print("1------\(NSThread.currentThread())")
        }
        queue.addOperationWithBlock { () -> Void in
            print("1------\(NSThread.currentThread())")
        }
        queue.addOperationWithBlock { () -> Void in
            print("1------\(NSThread.currentThread())")
        }
        queue.addOperationWithBlock { () -> Void in
            print("1------\(NSThread.currentThread())")
        }

Snip20150928_2.png

***添加queue.maxConcurrentOperationCount = 1
Snip20150928_3.png

可以看出来, 线程并不是一样的. 所以最大并发数的理解, 应该是我上面指出的

2.队列的取消,暂停,和恢复
1>取消队列的所有操作
- (void)cancelAllOpertions
注意: 也可以调用NSOperation的-(void)cancel方法取消单个操作. (总感觉单个任务取消不掉)
2>暂停和恢复队列
- (void)setSuspended:(BOOL)b// YES 代表暂停队列,NO代表恢复队列
- (BOOL)isSuspended

操作依赖

首先依赖其他的线程中也有说过 GCD ----<barrier, group都是依赖的意思>
NSOperation之间可以设置依赖来保证执行顺序.
操作之间添加依赖
[operationB addDependency:operationA] 操作B依赖于A
不同队列之间也可以进行任务的依赖, 但是需要注意的是, 不要相互依赖

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

推荐阅读更多精彩内容