iOS淺談多線程之NSOperation

NSInvocationOperation

1、在主線程中使用

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    NSURL *url = [NSURL URLWithString:@"abc"] ;
    NSInvocationOperation *inv = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(downloadImgFromURL:) object:url];
    [inv start];
}
- (void)downloadImgFromURL:(NSURL *)url {
    NSLog(@"%@___%@",url,[NSThread currentThread]);
}
2018-10-10 14:29:42.285163+0800 Visit_Thread[4244:242395] abc___<NSThread: 0x60000006ea80>{number = 1, name = main}

2亥宿、多線程

當(dāng)maxConcurrentOperationCount小于當(dāng)前任務(wù)數(shù)時(shí)會(huì)出現(xiàn)這樣的情況(很容易理解3個(gè)任務(wù),2條線程):

2條線程跑滿2個(gè)任務(wù),當(dāng)一個(gè)線程中的任務(wù)執(zhí)行完畢,再?gòu)年?duì)列中去取新的任務(wù)
如果設(shè)置最大并發(fā)數(shù)為1邮旷,那么任務(wù)將會(huì)串行執(zhí)行(在不同的線程執(zhí)行,但是執(zhí)行順序是串行的)
注意:串行執(zhí)行任務(wù) 不等于 只開一條線程
如果設(shè)置最大并發(fā)數(shù)為0蝇摸,那么任務(wù)將不會(huì)執(zhí)行

如果設(shè)置最大并發(fā)數(shù)為-1廊移,表示最大并發(fā)數(shù)不受限制

- (void)test7 {
     NSLog(@"start");
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    queue.maxConcurrentOperationCount = 2;
    NSURL *url = [NSURL URLWithString:@"abc"] ;
    NSInvocationOperation *task1 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(downloadImgFromURL1:) object:url];
    [queue addOperation:task1];
    NSInvocationOperation *task2 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(downloadImgFromURL2:) object:url];
    [queue addOperation:task2];
    NSInvocationOperation *task3 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(downloadImgFromURL3:) object:url];
    [queue addOperation:task3];
    NSLog(@"end");
}
- (void)downloadImgFromURL1:(NSURL *)url {
    for (int i = 0; i < 3; i++) {
        [NSThread sleepForTimeInterval:2];
        NSLog(@"1___%@",[NSThread currentThread]);
    }
    
}
- (void)downloadImgFromURL2:(NSURL *)url {
    for (int i = 0; i < 5; i++) {
        [NSThread sleepForTimeInterval:2];
        NSLog(@"2___%@",[NSThread currentThread]);
    }
}
- (void)downloadImgFromURL3:(NSURL *)url {
    for (int i = 0; i < 5; i++) {
        [NSThread sleepForTimeInterval:2];
        NSLog(@"3___%@",[NSThread currentThread]);
    }
}
2018-10-10 14:58:31.460019+0800 Visit_Thread[4774:280702] start
2018-10-10 14:58:31.460932+0800 Visit_Thread[4774:280702] end
2018-10-10 14:58:33.463473+0800 Visit_Thread[4774:280744] 2___<NSThread: 0x60400007b840>{number = 3, name = (null)}
2018-10-10 14:58:33.463479+0800 Visit_Thread[4774:280746] 1___<NSThread: 0x60000066a980>{number = 4, name = (null)}
2018-10-10 14:58:35.468851+0800 Visit_Thread[4774:280744] 2___<NSThread: 0x60400007b840>{number = 3, name = (null)}
2018-10-10 14:58:35.468870+0800 Visit_Thread[4774:280746] 1___<NSThread: 0x60000066a980>{number = 4, name = (null)}
2018-10-10 14:58:37.474366+0800 Visit_Thread[4774:280746] 1___<NSThread: 0x60000066a980>{number = 4, name = (null)}
2018-10-10 14:58:37.474367+0800 Visit_Thread[4774:280744] 2___<NSThread: 0x60400007b840>{number = 3, name = (null)}
2018-10-10 14:58:39.479901+0800 Visit_Thread[4774:280744] 2___<NSThread: 0x60400007b840>{number = 3, name = (null)}
2018-10-10 14:58:39.479903+0800 Visit_Thread[4774:280745] 3___<NSThread: 0x60400026a700>{number = 5, name = (null)}
2018-10-10 14:58:41.485467+0800 Visit_Thread[4774:280745] 3___<NSThread: 0x60400026a700>{number = 5, name = (null)}
2018-10-10 14:58:41.485467+0800 Visit_Thread[4774:280744] 2___<NSThread: 0x60400007b840>{number = 3, name = (null)}
2018-10-10 14:58:43.491001+0800 Visit_Thread[4774:280745] 3___<NSThread: 0x60400026a700>{number = 5, name = (null)}
2018-10-10 14:58:45.496507+0800 Visit_Thread[4774:280745] 3___<NSThread: 0x60400026a700>{number = 5, name = (null)}
2018-10-10 14:58:47.502031+0800 Visit_Thread[4774:280745] 3___<NSThread: 0x60400026a700>{number = 5, name = (null)}
如果最大線程數(shù)超過當(dāng)前任務(wù)數(shù),那么也只會(huì)開和當(dāng)前任務(wù)數(shù)相同的線程探入,多個(gè)任務(wù)狡孔,并發(fā)執(zhí)行:

queue.maxConcurrentOperationCount = 5;

2018-10-10 15:02:01.148009+0800 Visit_Thread[4837:285412] start
2018-10-10 15:02:01.148893+0800 Visit_Thread[4837:285412] end
2018-10-10 15:02:03.152383+0800 Visit_Thread[4837:285465] 2___<NSThread: 0x60000047cf40>{number = 5, name = (null)}
2018-10-10 15:02:03.152388+0800 Visit_Thread[4837:285467] 1___<NSThread: 0x60000047cdc0>{number = 3, name = (null)}
2018-10-10 15:02:03.152383+0800 Visit_Thread[4837:285468] 3___<NSThread: 0x60400026d1c0>{number = 4, name = (null)}
2018-10-10 15:02:05.155475+0800 Visit_Thread[4837:285467] 1___<NSThread: 0x60000047cdc0>{number = 3, name = (null)}
2018-10-10 15:02:05.155489+0800 Visit_Thread[4837:285468] 3___<NSThread: 0x60400026d1c0>{number = 4, name = (null)}
2018-10-10 15:02:05.155481+0800 Visit_Thread[4837:285465] 2___<NSThread: 0x60000047cf40>{number = 5, name = (null)}
2018-10-10 15:02:07.159810+0800 Visit_Thread[4837:285465] 2___<NSThread: 0x60000047cf40>{number = 5, name = (null)}
2018-10-10 15:02:07.159821+0800 Visit_Thread[4837:285467] 1___<NSThread: 0x60000047cdc0>{number = 3, name = (null)}
2018-10-10 15:02:07.159815+0800 Visit_Thread[4837:285468] 3___<NSThread: 0x60400026d1c0>{number = 4, name = (null)}
2018-10-10 15:02:09.163067+0800 Visit_Thread[4837:285465] 2___<NSThread: 0x60000047cf40>{number = 5, name = (null)}
2018-10-10 15:02:09.163066+0800 Visit_Thread[4837:285468] 3___<NSThread: 0x60400026d1c0>{number = 4, name = (null)}
2018-10-10 15:02:11.168004+0800 Visit_Thread[4837:285468] 3___<NSThread: 0x60400026d1c0>{number = 4, name = (null)}
2018-10-10 15:02:11.168000+0800 Visit_Thread[4837:285465] 2___<NSThread: 0x60000047cf40>{number = 5, name = (null)}

NSBlockOperation

1、在主線程中使用

如果任務(wù)開始之后再追加任務(wù)蜂嗽,程序會(huì)cache:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSBlockOperation addExecutionBlock:]: blocks cannot be added after the operation has started executing or finished

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    NSLog(@"start");
    NSBlockOperation *task1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"1___%@",[NSThread currentThread]);
    }];
    NSBlockOperation *task2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"2___%@",[NSThread currentThread]);
    }];
    NSBlockOperation *task3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"3___%@",[NSThread currentThread]);
    }];
   


    //追加任務(wù)
    [task1 addExecutionBlock:^{
        NSLog(@"1+++%@",[NSThread currentThread]);
    }];
    [task2 addExecutionBlock:^{
        NSLog(@"2+++%@",[NSThread currentThread]);
    }];
    [task3 addExecutionBlock:^{
        NSLog(@"3+++%@",[NSThread currentThread]);
    }];
    
    [task3 start];//先開始苗膝,先執(zhí)行
    [task1 start];
    [task2 start];
    NSLog(@"end");
}
2018-10-10 14:41:09.361581+0800 Visit_Thread[4436:258615] start
2018-10-10 14:41:09.361974+0800 Visit_Thread[4436:258615] 3___<NSThread: 0x60000007cf00>{number = 1, name = main}
2018-10-10 14:41:09.361975+0800 Visit_Thread[4436:259265] 3+++<NSThread: 0x6000006667c0>{number = 8, name = (null)}
2018-10-10 14:41:09.362169+0800 Visit_Thread[4436:258615] 1___<NSThread: 0x60000007cf00>{number = 1, name = main}
2018-10-10 14:41:09.362182+0800 Visit_Thread[4436:259265] 1+++<NSThread: 0x6000006667c0>{number = 8, name = (null)}
2018-10-10 14:41:09.362635+0800 Visit_Thread[4436:259265] 2+++<NSThread: 0x6000006667c0>{number = 8, name = (null)}
2018-10-10 14:41:09.362643+0800 Visit_Thread[4436:258615] 2___<NSThread: 0x60000007cf00>{number = 1, name = main}
2018-10-10 14:41:09.362886+0800 Visit_Thread[4436:258615] end


2018-10-10 14:40:22.773672+0800 Visit_Thread[4436:258615] start
2018-10-10 14:40:22.774083+0800 Visit_Thread[4436:258615] 3___<NSThread: 0x60000007cf00>{number = 1, name = main}
2018-10-10 14:40:22.774114+0800 Visit_Thread[4436:258911] 3+++<NSThread: 0x60400046fc80>{number = 5, name = (null)}
2018-10-10 14:40:22.774752+0800 Visit_Thread[4436:258911] 1+++<NSThread: 0x60400046fc80>{number = 5, name = (null)}
2018-10-10 14:40:22.774753+0800 Visit_Thread[4436:258615] 1___<NSThread: 0x60000007cf00>{number = 1, name = main}
2018-10-10 14:40:22.774943+0800 Visit_Thread[4436:258615] 2___<NSThread: 0x60000007cf00>{number = 1, name = main}
2018-10-10 14:40:22.774951+0800 Visit_Thread[4436:258911] 2+++<NSThread: 0x60400046fc80>{number = 5, name = (null)}
2018-10-10 14:40:22.775110+0800 Visit_Thread[4436:258615] end

通過打印結(jié)果可知:先開始,先執(zhí)行植旧;
但是開始的任務(wù)中辱揭,是先執(zhí)行原任務(wù)還是先執(zhí)行追加任務(wù)离唐,這個(gè)是不確定的;
原任務(wù)是在主線程中執(zhí)行的问窃,但是追加的任務(wù)都是在子線程中執(zhí)行的亥鬓;

多線程

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    NSLog(@"start");
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];
//     queue.maxConcurrentOperationCount = 5;
    NSBlockOperation *task1 = [NSBlockOperation blockOperationWithBlock:^{
        for (int i = 0; i < 3; i++) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"1___%@",[NSThread currentThread]);
        }
    }];
    NSBlockOperation *task2 = [NSBlockOperation blockOperationWithBlock:^{
        for (int i = 0; i < 3; i++) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"2___%@",[NSThread currentThread]);
        }
    }];
    NSBlockOperation *task3 = [NSBlockOperation blockOperationWithBlock:^{
        for (int i = 0; i < 3; i++) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"3___%@",[NSThread currentThread]);
        }
    }];
    //追加任務(wù)
    [task1 addExecutionBlock:^{
        for (int i = 0; i < 3; i++) {
            [NSThread sleepForTimeInterval:1];
            NSLog(@"1+++%@",[NSThread currentThread]);
        }
    }];
    [task2 addExecutionBlock:^{
        for (int i = 0; i < 3; i++) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"2+++%@",[NSThread currentThread]);
        }
    }];
    [task3 addExecutionBlock:^{
        for (int i = 0; i < 3; i++) {
            [NSThread sleepForTimeInterval:3];
            NSLog(@"3+++%@",[NSThread currentThread]);
        }
    }];
    [queue addOperation:task1];
    [queue addOperation:task2];
    [queue addOperation:task3];
    NSLog(@"end");
}
2018-10-10 15:13:38.464338+0800 Visit_Thread[5027:297309] start
2018-10-10 15:13:38.464920+0800 Visit_Thread[5027:297309] end
2018-10-10 15:13:39.465737+0800 Visit_Thread[5027:297386] 1+++<NSThread: 0x60400027e980>{number = 3, name = (null)}
2018-10-10 15:13:40.469689+0800 Visit_Thread[5027:297364] 2___<NSThread: 0x604000465c40>{number = 5, name = (null)}
2018-10-10 15:13:40.469701+0800 Visit_Thread[5027:297365] 1___<NSThread: 0x604000465b80>{number = 4, name = (null)}
2018-10-10 15:13:40.469708+0800 Visit_Thread[5027:297386] 1+++<NSThread: 0x60400027e980>{number = 3, name = (null)}
2018-10-10 15:13:40.469735+0800 Visit_Thread[5027:297367] 3___<NSThread: 0x600000670640>{number = 6, name = (null)}
2018-10-10 15:13:40.469735+0800 Visit_Thread[5027:297385] 2+++<NSThread: 0x600000670880>{number = 7, name = (null)}
2018-10-10 15:13:41.468790+0800 Visit_Thread[5027:297366] 3+++<NSThread: 0x604000465dc0>{number = 8, name = (null)}
2018-10-10 15:13:41.475239+0800 Visit_Thread[5027:297386] 1+++<NSThread: 0x60400027e980>{number = 3, name = (null)}
2018-10-10 15:13:42.475216+0800 Visit_Thread[5027:297367] 3___<NSThread: 0x600000670640>{number = 6, name = (null)}
2018-10-10 15:13:42.475216+0800 Visit_Thread[5027:297365] 1___<NSThread: 0x604000465b80>{number = 4, name = (null)}
2018-10-10 15:13:42.475227+0800 Visit_Thread[5027:297364] 2___<NSThread: 0x604000465c40>{number = 5, name = (null)}
2018-10-10 15:13:42.475260+0800 Visit_Thread[5027:297385] 2+++<NSThread: 0x600000670880>{number = 7, name = (null)}
2018-10-10 15:13:44.469294+0800 Visit_Thread[5027:297366] 3+++<NSThread: 0x604000465dc0>{number = 8, name = (null)}
2018-10-10 15:13:44.479592+0800 Visit_Thread[5027:297364] 2___<NSThread: 0x604000465c40>{number = 5, name = (null)}
2018-10-10 15:13:44.479596+0800 Visit_Thread[5027:297367] 3___<NSThread: 0x600000670640>{number = 6, name = (null)}
2018-10-10 15:13:44.479592+0800 Visit_Thread[5027:297365] 1___<NSThread: 0x604000465b80>{number = 4, name = (null)}
2018-10-10 15:13:44.479641+0800 Visit_Thread[5027:297385] 2+++<NSThread: 0x600000670880>{number = 7, name = (null)}
2018-10-10 15:13:47.471226+0800 Visit_Thread[5027:297366] 3+++<NSThread: 0x604000465dc0>{number = 8, name = (null)}

NSOperation的暫停、恢復(fù)和取消

- (IBAction)start:(id)sender {
    NSLog(@"start");
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    _queue = queue;
         queue.maxConcurrentOperationCount = 1;
    [queue addOperationWithBlock:^{
        for (int i = 0; i < 3; i++) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"1___%@",[NSThread currentThread]);
        }
    }];
    [queue addOperationWithBlock:^{
        for (int i = 0; i < 5; i++) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"2___%@",[NSThread currentThread]);
        }
    }];
    [queue addOperationWithBlock:^{
        for (int i = 0; i < 5; i++) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"3___%@",[NSThread currentThread]);
        }
    }];
    [queue addOperationWithBlock:^{
        for (int i = 0; i < 3; i++) {
            [NSThread sleepForTimeInterval:2];
            NSLog(@"4___%@",[NSThread currentThread]);
        }
    }];
    NSLog(@"end");
}
- (IBAction)suspend:(id)sender {
    NSLog(@"暫停");
    //不能暫停正在處于執(zhí)行狀態(tài)的任務(wù)
    [_queue setSuspended:YES];
}
- (IBAction)goOn:(id)sender {
    NSLog(@"繼續(xù)");
    [_queue setSuspended:NO];
}
- (IBAction)cancel:(id)sender {
    NSLog(@"取消");
    //取消之后域庇,不能恢復(fù)
    [_queue cancelAllOperations];
}

打印結(jié)果:

2018-10-10 17:05:36.939569+0800 Visit_Thread[6591:388486] start
2018-10-10 17:05:36.940215+0800 Visit_Thread[6591:388486] end
2018-10-10 17:05:38.945240+0800 Visit_Thread[6591:388556] 1___<NSThread: 0x604000462f00>{number = 3, name = (null)}
2018-10-10 17:05:40.948462+0800 Visit_Thread[6591:388556] 1___<NSThread: 0x604000462f00>{number = 3, name = (null)}
2018-10-10 17:05:41.736979+0800 Visit_Thread[6591:388486] 暫停
2018-10-10 17:05:42.948923+0800 Visit_Thread[6591:388556] 1___<NSThread: 0x604000462f00>{number = 3, name = (null)}
2018-10-10 17:06:01.016564+0800 Visit_Thread[6591:388486] 繼續(xù)
2018-10-10 17:06:03.022025+0800 Visit_Thread[6591:388809] 2___<NSThread: 0x604000463ec0>{number = 4, name = (null)}
2018-10-10 17:06:05.027504+0800 Visit_Thread[6591:388809] 2___<NSThread: 0x604000463ec0>{number = 4, name = (null)}
2018-10-10 17:06:06.148510+0800 Visit_Thread[6591:388486] 暫停
2018-10-10 17:06:07.028798+0800 Visit_Thread[6591:388809] 2___<NSThread: 0x604000463ec0>{number = 4, name = (null)}
2018-10-10 17:06:09.031857+0800 Visit_Thread[6591:388809] 2___<NSThread: 0x604000463ec0>{number = 4, name = (null)}
2018-10-10 17:06:11.032833+0800 Visit_Thread[6591:388809] 2___<NSThread: 0x604000463ec0>{number = 4, name = (null)}
2018-10-10 17:06:14.879380+0800 Visit_Thread[6591:388486] 繼續(xù)
2018-10-10 17:06:16.882917+0800 Visit_Thread[6591:388809] 3___<NSThread: 0x604000463ec0>{number = 4, name = (null)}
2018-10-10 17:06:18.885551+0800 Visit_Thread[6591:388809] 3___<NSThread: 0x604000463ec0>{number = 4, name = (null)}
2018-10-10 17:06:20.889610+0800 Visit_Thread[6591:388809] 3___<NSThread: 0x604000463ec0>{number = 4, name = (null)}
2018-10-10 17:06:22.890000+0800 Visit_Thread[6591:388809] 3___<NSThread: 0x604000463ec0>{number = 4, name = (null)}
2018-10-10 17:06:24.893687+0800 Visit_Thread[6591:388809] 3___<NSThread: 0x604000463ec0>{number = 4, name = (null)}
2018-10-10 17:06:26.896813+0800 Visit_Thread[6591:388893] 4___<NSThread: 0x60400026e640>{number = 5, name = (null)}
2018-10-10 17:06:28.898334+0800 Visit_Thread[6591:388893] 4___<NSThread: 0x60400026e640>{number = 5, name = (null)}
2018-10-10 17:06:30.898909+0800 Visit_Thread[6591:388893] 4___<NSThread: 0x60400026e640>{number = 5, name = (null)}
2018-10-10 17:06:32.212768+0800 Visit_Thread[6591:388486] 取消

結(jié)合打印結(jié)果可知:

maxConcurrentOperationCount為1時(shí)串行執(zhí)行
串行執(zhí)行不等于只開一條線程
不能暫停正在處于執(zhí)行狀態(tài)的任務(wù)
同樣的嵌戈,也不能取消正在執(zhí)行的任務(wù),必須要等當(dāng)前任務(wù)執(zhí)行完畢才能取消
任務(wù)取消之后听皿,便不能恢復(fù)

繼承NSOperation

#import <UIKit/UIKit.h>

@interface DownloadImgOperation : NSOperation
- (instancetype)initWithURL:(NSURL *)url imageView:(UIImageView *)imageView;
@end
#import "DownloadImgOperation.h"

@interface DownloadImgOperation()
@property (strong, nonatomic) NSURL *url;
@property (strong, nonatomic) UIImageView *imageView;
@end
@implementation DownloadImgOperation
- (void)main {//重寫main方法
    NSData *data = [[NSData alloc]initWithContentsOfURL:self.url];
    UIImage *image = [[UIImage alloc]initWithData:data];
    if (image != nil) {
        [self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES];
    }else {
        NSLog(@"download error");
    }
    
}
- (instancetype)initWithURL:(NSURL *)url imageView:(UIImageView *)imageView {
    if (self = [super init]) {
        self.imageView = imageView;
        self.url = url;
    }
    return self;
}
- (void)updateUI:(UIImage *)image {
    self.imageView.image =image;
}
@end

如果是在自定義Operation中的main方法中有耗時(shí)操作熟呛,那么需要特別處理:

- (void)main {//重寫main方法
    for (int i = 0; i < 5; i++) {
        [NSThread sleepForTimeInterval:2];
        NSLog(@"1___%@",[NSThread currentThread]);
    }
    for (int i = 0; i < 5; i++) {
        [NSThread sleepForTimeInterval:2];
        NSLog(@"2___%@",[NSThread currentThread]);
    }
    for (int i = 0; i < 5; i++) {
        [NSThread sleepForTimeInterval:2];
        NSLog(@"3___%@",[NSThread currentThread]);
    }
}

調(diào)用注意點(diǎn):

1、暫定功能不起作用尉姨,因?yàn)闀和J轻槍?duì)多個(gè)Operation的庵朝,開始時(shí)只有一個(gè),暫停時(shí)需要等這個(gè)Operation執(zhí)行完畢又厉,所以沒有意義九府,取消也是如此。那么繼續(xù)也便沒有意義覆致。
2侄旬、但是可以實(shí)現(xiàn)通過改進(jìn),來實(shí)現(xiàn)取消功能(在main方法中做更改):
- (IBAction)start:(id)sender {
    NSLog(@"start");
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    _queue = queue;
    queue.maxConcurrentOperationCount = 1;
    DownloadImgOperation *operation = [[DownloadImgOperation alloc]init];
    [_queue addOperation:operation];
    NSLog(@"end");
}
- (IBAction)cancel:(id)sender {
    NSLog(@"取消");
    [_queue cancelAllOperations];
}

更改main方法:

- (void)main {//重寫main方法
    for (int i = 0; i < 5; i++) {
        [NSThread sleepForTimeInterval:2];
        //雖然在此處可以做到精確控制篷朵,但是如果循環(huán)次數(shù)太多勾怒,每次都需要做判斷婆排,所以不建議這樣使用
//        if(self.isCancelled) return;
        NSLog(@"1___%@",[NSThread currentThread]);
    }
    if(self.isCancelled) return;
    for (int i = 0; i < 5; i++) {
        [NSThread sleepForTimeInterval:2];
        NSLog(@"2___%@",[NSThread currentThread]);
    }
    if(self.isCancelled) return;
    for (int i = 0; i < 5; i++) {
        [NSThread sleepForTimeInterval:2];
        NSLog(@"3___%@",[NSThread currentThread]);
    }
}

設(shè)置NSOperation的依賴與監(jiān)聽

- (IBAction)start:(id)sender {
    NSLog(@"start");
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    NSOperationQueue *queue2 = [[NSOperationQueue alloc]init];
    NSBlockOperation *task1 = [NSBlockOperation blockOperationWithBlock:^{
        for (int i = 0; i < 3; i++) {
            [NSThread sleepForTimeInterval:1];
            NSLog(@"1___%@",[NSThread currentThread]);
        }
    }];
    NSBlockOperation *task2 = [NSBlockOperation blockOperationWithBlock:^{
        for (int i = 0; i < 5; i++) {
            [NSThread sleepForTimeInterval:1];
            NSLog(@"2___%@",[NSThread currentThread]);
        }
    }];
    NSBlockOperation *task3 = [NSBlockOperation blockOperationWithBlock:^{
        for (int i = 0; i < 5; i++) {
            [NSThread sleepForTimeInterval:1];
            NSLog(@"3___%@",[NSThread currentThread]);
        }
    }];
    NSBlockOperation *task4 = [NSBlockOperation blockOperationWithBlock:^{
        for (int i = 0; i < 3; i++) {
            [NSThread sleepForTimeInterval:1];
            NSLog(@"4___%@",[NSThread currentThread]);
        }
    }];
    //設(shè)置依賴:
    //
    [task2 addDependency:task1];//必須等task1的任務(wù)執(zhí)行完畢task2才能執(zhí)行
    [task3 addDependency:task2];//必須等task2的任務(wù)執(zhí)行完畢task3才能執(zhí)行
    task1.completionBlock = ^ {
        NSLog(@"task1執(zhí)行完畢了————%@",[NSThread currentThread]);
    };
    [queue addOperation:task1];
    [queue2 addOperation:task2];
    [queue2 addOperation:task3];
    [queue addOperation:task4];
    NSLog(@"end");
}
打印結(jié)果:
2018-10-10 18:25:08.234783+0800 Visit_Thread[7925:466651] start
2018-10-10 18:25:08.235548+0800 Visit_Thread[7925:466651] end
2018-10-10 18:25:09.238803+0800 Visit_Thread[7925:466803] 4___<NSThread: 0x600000478880>{number = 4, name = (null)}
2018-10-10 18:25:09.238801+0800 Visit_Thread[7925:466707] 1___<NSThread: 0x600000476900>{number = 3, name = (null)}
2018-10-10 18:25:10.242784+0800 Visit_Thread[7925:466803] 4___<NSThread: 0x600000478880>{number = 4, name = (null)}
2018-10-10 18:25:10.242784+0800 Visit_Thread[7925:466707] 1___<NSThread: 0x600000476900>{number = 3, name = (null)}
2018-10-10 18:25:11.247918+0800 Visit_Thread[7925:466803] 4___<NSThread: 0x600000478880>{number = 4, name = (null)}
2018-10-10 18:25:11.247918+0800 Visit_Thread[7925:466707] 1___<NSThread: 0x600000476900>{number = 3, name = (null)}
2018-10-10 18:25:11.248278+0800 Visit_Thread[7925:466707] task1執(zhí)行完畢了————<NSThread: 0x600000476900>{number = 3, name = (null)}
2018-10-10 18:25:12.248466+0800 Visit_Thread[7925:466810] 2___<NSThread: 0x60000047f3c0>{number = 5, name = (null)}
2018-10-10 18:25:13.252236+0800 Visit_Thread[7925:466810] 2___<NSThread: 0x60000047f3c0>{number = 5, name = (null)}
2018-10-10 18:25:14.256300+0800 Visit_Thread[7925:466810] 2___<NSThread: 0x60000047f3c0>{number = 5, name = (null)}
2018-10-10 18:25:15.261807+0800 Visit_Thread[7925:466810] 2___<NSThread: 0x60000047f3c0>{number = 5, name = (null)}
2018-10-10 18:25:16.267055+0800 Visit_Thread[7925:466810] 2___<NSThread: 0x60000047f3c0>{number = 5, name = (null)}
2018-10-10 18:25:17.267466+0800 Visit_Thread[7925:466707] 3___<NSThread: 0x600000476900>{number = 3, name = (null)}
2018-10-10 18:25:18.272417+0800 Visit_Thread[7925:466707] 3___<NSThread: 0x600000476900>{number = 3, name = (null)}
2018-10-10 18:25:19.275128+0800 Visit_Thread[7925:466707] 3___<NSThread: 0x600000476900>{number = 3, name = (null)}
2018-10-10 18:25:20.280244+0800 Visit_Thread[7925:466707] 3___<NSThread: 0x600000476900>{number = 3, name = (null)}
2018-10-10 18:25:21.281868+0800 Visit_Thread[7925:466707] 3___<NSThread: 0x600000476900>{number = 3, name = (null)}

NSOperation的線程間的通信

1声旺、方式1
- (IBAction)start:(id)sender {
    NSLog(@"start");
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];
//    [queue addOperationWithBlock:^{
//        //coding
//    }];
    __block UIImage *img ;
    NSBlockOperation *task = [NSBlockOperation blockOperationWithBlock:^{
        NSURL *url = [NSURL URLWithString:@"http://c.hiphotos.baidu.com/image/h%3D300/sign=c635d3753efa828bce239be3cd1f41cd/0eb30f2442a7d933b29eb303a04bd11373f0018f.jpg"];
        NSData *data = [NSData dataWithContentsOfURL:url];
        img = [UIImage imageWithData:data];
    }];
    task.completionBlock = ^ {
        NSLog(@"task1執(zhí)行完畢了————%@",[NSThread currentThread]);
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            NSLog(@"%@",[NSThread currentThread]);
            self.imgView.image = img;
        }];
    };
    [queue addOperation:task];
    NSLog(@"end");
}
2、方式2
- (IBAction)start:(id)sender {
    NSLog(@"start");
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    [queue addOperationWithBlock:^{
        //coding
        NSLog(@"%@",[NSThread currentThread]);
    }];
    __block UIImage *img ;
    NSBlockOperation *task = [NSBlockOperation blockOperationWithBlock:^{
        NSURL *url = [NSURL URLWithString:@"http://c.hiphotos.baidu.com/image/h%3D300/sign=c635d3753efa828bce239be3cd1f41cd/0eb30f2442a7d933b29eb303a04bd11373f0018f.jpg"];
        NSData *data = [NSData dataWithContentsOfURL:url];
        UIImage *img = [UIImage imageWithData:data];
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            self.imgView.image = img;
        }];
    }];
    [queue addOperation:task];
    NSLog(@"end");
}

練習(xí):將2張圖片合成一張圖片并展示

- (IBAction)start:(id)sender {
    NSLog(@"start");
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    __block UIImage *img1 ;
    NSBlockOperation *task1 = [NSBlockOperation blockOperationWithBlock:^{
        NSURL *url = [NSURL URLWithString:@"http://c.hiphotos.baidu.com/image/h%3D300/sign=c635d3753efa828bce239be3cd1f41cd/0eb30f2442a7d933b29eb303a04bd11373f0018f.jpg"];
        NSData *data = [NSData dataWithContentsOfURL:url];
        img1 = [UIImage imageWithData:data];
    }];
    __block UIImage *img2 ;
    NSBlockOperation *task2 = [NSBlockOperation blockOperationWithBlock:^{
        NSURL *url = [NSURL URLWithString:@"http://b.hiphotos.baidu.com/image/h%3D300/sign=b48b76f776899e51678e3c1472a6d990/e824b899a9014c08ef778daf077b02087bf4f468.jpg"];
        NSData *data = [NSData dataWithContentsOfURL:url];
        img2 = [UIImage imageWithData:data];
    }];
    NSBlockOperation *task3 = [NSBlockOperation blockOperationWithBlock:^{
        UIGraphicsBeginImageContext(CGSizeMake(200, 200));
        [img1 drawInRect:CGRectMake(0, 0, 200, 100)];
        [img2 drawInRect:CGRectMake(0, 100, 200, 100)];
        UIImage *combinImg = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        [[NSOperationQueue mainQueue]addOperationWithBlock:^{
            self.imgView.image = combinImg;
        }];
    }];
    
    [task3 addDependency:task1];
    [task3 addDependency:task2];
    [queue addOperation:task1];
    [queue addOperation:task2];
    [queue addOperation:task3];
    NSLog(@"end");
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末段只,一起剝皮案震驚了整個(gè)濱河市腮猖,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌赞枕,老刑警劉巖澈缺,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件涉波,死亡現(xiàn)場(chǎng)離奇詭異命满,居然都是意外死亡谭溉,警方通過查閱死者的電腦和手機(jī)艰猬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門拦耐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來轩猩,“玉大人曙旭,你說我怎么就攤上這事茧球⊙恼辏” “怎么了枪狂?”我有些...
    開封第一講書人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵危喉,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我州疾,道長(zhǎng)辜限,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任严蓖,我火速辦了婚禮薄嫡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘谈飒。我一直安慰自己岂座,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開白布杭措。 她就那樣靜靜地躺著费什,像睡著了一般。 火紅的嫁衣襯著肌膚如雪手素。 梳的紋絲不亂的頭發(fā)上鸳址,一...
    開封第一講書人閱讀 51,554評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音泉懦,去河邊找鬼稿黍。 笑死,一個(gè)胖子當(dāng)著我的面吹牛崩哩,可吹牛的內(nèi)容都是我干的巡球。 我是一名探鬼主播,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼邓嘹,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼酣栈!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起汹押,我...
    開封第一講書人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤矿筝,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后棚贾,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體窖维,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年妙痹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了铸史。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡怯伊,死狀恐怖琳轿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤利赋,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布水评,位于F島的核電站,受9級(jí)特大地震影響媚送,放射性物質(zhì)發(fā)生泄漏中燥。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一塘偎、第九天 我趴在偏房一處隱蔽的房頂上張望疗涉。 院中可真熱鬧,春花似錦吟秩、人聲如沸咱扣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽闹伪。三九已至,卻和暖如春壮池,著一層夾襖步出監(jiān)牢的瞬間偏瓤,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工椰憋, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留厅克,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓橙依,卻偏偏與公主長(zhǎng)得像证舟,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子窗骑,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容