多线程 & 网络

iOS多线程:NSOperation

2020-04-23  本文已影响0人  码小菜
别墅

目录
一,NSOperation
二,NSInvocationOperation
三,NSBlockOperation
四,NSOperationQueue(一)
五,NSOperationQueue(二)
六,自定义NSOperation

一,NSOperation

1,它是一个抽象类,不能直接使用,只能使用其子类

2,执行方式

二,NSInvocationOperation

1,initWithTarget:

- (void)viewDidLoad {
    [super viewDidLoad];
 
    NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(performOperation) object:nil];
    [operation start];
}

- (void)performOperation {
    NSLog(@"%s---%@", __func__, [NSThread currentThread]);
}

// 打印
-[ViewController performOperation]---<NSThread: 0x60000313fc40>{number = 1, name = main}

2,initWithInvocation:

- (void)viewDidLoad {
    [super viewDidLoad];
 
    NSMethodSignature *signature = [self methodSignatureForSelector:@selector(performOperation)];
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
    invocation.target = self;
    invocation.selector = @selector(performOperation);
    
    NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithInvocation:invocation];
    [operation start];
}

// 打印
-[ViewController performOperation]---<NSThread: 0x6000014490c0>{number = 1, name = main}
三,NSBlockOperation

1,一个任务:同步执行

- (void)viewDidLoad {
    [super viewDidLoad];
 
    NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"blockOperationWithBlock---%@", [NSThread currentThread]);
    }];
    [operation start];
}

// 打印
blockOperationWithBlock---<NSThread: 0x60000315ad40>{number = 1, name = main}

2,多个任务:其中一个同步执行,其他的都异步执行

- (void)viewDidLoad {
    [super viewDidLoad];
 
    NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"blockOperationWithBlock---%@", [NSThread currentThread]);
    }];

    [operation addExecutionBlock:^{
        NSLog(@"addExecutionBlock1---%@", [NSThread currentThread]);
    }];

    [operation addExecutionBlock:^{
        NSLog(@"addExecutionBlock2---%@", [NSThread currentThread]);
    }];
    
    [operation start];
}

// 打印
blockOperationWithBlock---<NSThread: 0x60000119ad00>{number = 5, name = (null)}
addExecutionBlock1---<NSThread: 0x6000011edf80>{number = 6, name = (null)}
addExecutionBlock2---<NSThread: 0x60000119cf80>{number = 1, name = main}
四,NSOperationQueue(一)

1,添加到队列中的操作都是异步执行

- (void)viewDidLoad {
    [super viewDidLoad];
 
    NSOperationQueue *queue = [NSOperationQueue new];
    
    NSInvocationOperation *operation1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(performOperation) object:nil];
    
    NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"blockOperationWithBlock---%@", [NSThread currentThread]);
    }];
    
    [queue addOperation:operation1];
    [queue addOperation:operation2];
    [queue addOperationWithBlock:^{
        NSLog(@"addOperationWithBlock---%@", [NSThread currentThread]);
    }];
}

- (void)performOperation {
    NSLog(@"%s---%@", __func__, [NSThread currentThread]);
}

// 打印
blockOperationWithBlock---<NSThread: 0x600003d8e400>{number = 6, name = (null)}
addOperationWithBlock---<NSThread: 0x600003d98800>{number = 7, name = (null)}
-[ViewController performOperation]---<NSThread: 0x600003db1a00>{number = 4, name = (null)}

2,添加依赖可以设置执行顺序

- (void)viewDidLoad {
    [super viewDidLoad];
 
    NSOperationQueue *queue = [NSOperationQueue new];
    
    NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"blockOperationWithBlock1---%@", [NSThread currentThread]);
    }];
    
    NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"blockOperationWithBlock2---%@", [NSThread currentThread]);
    }];
    
    NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"blockOperationWithBlock3---%@", [NSThread currentThread]);
    }];
    
    [operation1 addDependency:operation2];
    [operation2 addDependency:operation3];
    
    [queue addOperation:operation1];
    [queue addOperation:operation2];
    [queue addOperation:operation3];
}

// 打印
blockOperationWithBlock3---<NSThread: 0x6000002c2a40>{number = 5, name = (null)}
blockOperationWithBlock2---<NSThread: 0x6000002c2a40>{number = 5, name = (null)}
blockOperationWithBlock1---<NSThread: 0x6000002ce9c0>{number = 6, name = (null)}

3,优先级不能决定执行顺序

- (void)viewDidLoad {
    [super viewDidLoad];
 
    NSOperationQueue *queue = [NSOperationQueue new];
    
    NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"blockOperationWithBlock1---%@", [NSThread currentThread]);
    }];
    operation1.queuePriority = NSOperationQueuePriorityLow;
    
    NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"blockOperationWithBlock2---%@", [NSThread currentThread]);
    }];
    operation2.queuePriority = NSOperationQueuePriorityNormal;
    
    NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"blockOperationWithBlock3---%@", [NSThread currentThread]);
    }];
    operation3.queuePriority = NSOperationQueuePriorityHigh;
    
    [queue addOperation:operation1];
    [queue addOperation:operation2];
    [queue addOperation:operation3];
}

// 打印
blockOperationWithBlock2---<NSThread: 0x6000007519c0>{number = 6, name = (null)}
blockOperationWithBlock1---<NSThread: 0x60000075a280>{number = 5, name = (null)}
blockOperationWithBlock3---<NSThread: 0x6000007586c0>{number = 4, name = (null)}

4,设置队列的最大并发数

- (void)viewDidLoad {
    [super viewDidLoad];
 
    NSOperationQueue *queue = [NSOperationQueue new];
    // 同时只能执行一个操作
    queue.maxConcurrentOperationCount = 1;
    
    NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"blockOperationWithBlock1---%@", [NSThread currentThread]);
        sleep(1.0);
    }];
    
    NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"blockOperationWithBlock2---%@", [NSThread currentThread]);
        sleep(1.0);
    }];
    
    NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"blockOperationWithBlock3---%@", [NSThread currentThread]);
        sleep(1.0);
    }];
    
    [queue addOperation:operation1];
    [queue addOperation:operation2];
    [queue addOperation:operation3];
}

// 打印
16:15:09.331128+0800 Demo[97301:24562664] blockOperationWithBlock1---<NSThread: 0x6000038741c0>{number = 7, name = (null)}
16:15:10.334874+0800 Demo[97301:24562666] blockOperationWithBlock2---<NSThread: 0x600003850d40>{number = 4, name = (null)}
16:15:11.340412+0800 Demo[97301:24562668] blockOperationWithBlock3---<NSThread: 0x6000038549c0>{number = 5, name = (null)}

5,添加栅栏操作

- (void)viewDidLoad {
    [super viewDidLoad];
 
    NSOperationQueue *queue = [NSOperationQueue new];
    
    NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"blockOperationWithBlock1---%@", [NSThread currentThread]);
        sleep(1.0);
    }];
    
    NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"blockOperationWithBlock2---%@", [NSThread currentThread]);
        sleep(1.0);
    }];
    
    NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"blockOperationWithBlock3---%@", [NSThread currentThread]);
        sleep(1.0);
    }];
    
    NSBlockOperation *operation4 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"blockOperationWithBlock4---%@", [NSThread currentThread]);
        sleep(1.0);
    }];
    
    [queue addOperation:operation1];
    [queue addOperation:operation2];

    [queue addBarrierBlock:^{
        NSLog(@"addBarrierBlock---%@", [NSThread currentThread]);
        sleep(1.0);
    }];

    [queue addOperation:operation3];
    [queue addOperation:operation4];
}

// 打印
07:03:04.497862+0800 Demo[98215:24588685] blockOperationWithBlock1---<NSThread: 0x600000b69580>{number = 6, name = (null)}
07:03:04.497866+0800 Demo[98215:24588689] blockOperationWithBlock2---<NSThread: 0x600000b40080>{number = 3, name = (null)}
07:03:05.503058+0800 Demo[98215:24588689] addBarrierBlock---<NSThread: 0x600000b40080>{number = 3, name = (null)}
07:03:06.504957+0800 Demo[98215:24588689] blockOperationWithBlock4---<NSThread: 0x600000b40080>{number = 3, name = (null)}
07:03:06.504976+0800 Demo[98215:24588685] blockOperationWithBlock3---<NSThread: 0x600000b69580>{number = 6, name = (null)}
五,NSOperationQueue(二)

1,暂停和恢复

- (void)viewDidLoad {
    [super viewDidLoad];
 
    NSOperationQueue *queue = [NSOperationQueue new];
    queue.maxConcurrentOperationCount = 1;
    
    NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"blockOperationWithBlock1---%@", [NSThread currentThread]);
        sleep(1.0);
    }];
    
    NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"blockOperationWithBlock2---%@", [NSThread currentThread]);
        sleep(1.0);
    }];
    
    NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"blockOperationWithBlock3---%@", [NSThread currentThread]);
        sleep(1.0);
    }];
    
    [queue addOperation:operation1];
    [queue addOperation:operation2];
    [queue addOperation:operation3];
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        queue.suspended = YES;
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            queue.suspended = NO;
        });
    });
}

// 打印
07:26:36.604627+0800 Demo[98630:24601404] blockOperationWithBlock1---<NSThread: 0x6000027c1a00>{number = 6, name = (null)}
07:26:37.608845+0800 Demo[98630:24601405] blockOperationWithBlock2---<NSThread: 0x6000027faf40>{number = 4, name = (null)}
07:26:40.693889+0800 Demo[98630:24601405] blockOperationWithBlock3---<NSThread: 0x6000027faf40>{number = 4, name = (null)}

2,取消操作

- (void)viewDidLoad {
    [super viewDidLoad];
 
    NSOperationQueue *queue = [NSOperationQueue new];
    queue.maxConcurrentOperationCount = 1;
    
    NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"blockOperationWithBlock1---%@", [NSThread currentThread]);
        sleep(3.0);
    }];
    
    NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"blockOperationWithBlock2---%@", [NSThread currentThread]);
    }];
    
    NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"blockOperationWithBlock3---%@", [NSThread currentThread]);
    }];
    
    [queue addOperation:operation1];
    [queue addOperation:operation2];
    [queue addOperation:operation3];
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [operation2 cancel];
    });
}

// 打印
07:46:44.497224+0800 Demo[98851:24610141] blockOperationWithBlock1---<NSThread: 0x600000098000>{number = 7, name = (null)}
07:46:47.501865+0800 Demo[98851:24610144] blockOperationWithBlock3---<NSThread: 0x6000000b1b80>{number = 6, name = (null)}
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    [queue cancelAllOperations];
});

// 打印
blockOperationWithBlock1---<NSThread: 0x60000360a980>{number = 5, name = (null)}

⚠️注意⚠️:正在执行的操作是无法取消的

3,监听操作执行完成

1>completionBlock

- (void)viewDidLoad {
   [super viewDidLoad];
   
   NSOperationQueue *queue = [NSOperationQueue new];
   
   NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
       NSLog(@"blockOperationWithBlock---%@", [NSThread currentThread]);
       sleep(3.0);
   }];
   
   operation.completionBlock = ^{
       NSLog(@"操作已执行完成---%@", [NSThread currentThread]);
   };
   
   [queue addOperation:operation];
}

// 打印
10:15:43.988124+0800 Demo[543:24663415] blockOperationWithBlock---<NSThread: 0x600003a7b240>{number = 6, name = (null)}
10:15:46.990208+0800 Demo[543:24663412] 操作已执行完成---<NSThread: 0x600003a46740>{number = 3, name = (null)}

2>waitUntilFinished

- (void)viewDidLoad {
   [super viewDidLoad];
   
   NSOperationQueue *queue = [NSOperationQueue new];
   
   NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
       NSLog(@"blockOperationWithBlock---%@", [NSThread currentThread]);
       sleep(3.0);
   }];
   
   [queue addOperation:operation];
   
   // 会阻塞当前线程
   [operation waitUntilFinished];
   NSLog(@"操作已执行完成---%@", [NSThread currentThread]);
}

// 打印
10:18:14.938398+0800 Demo[570:24665122] blockOperationWithBlock---<NSThread: 0x600001fe4440>{number = 6, name = (null)}
10:18:17.943464+0800 Demo[570:24665010] 操作已执行完成---<NSThread: 0x600001f82d00>{number = 1, name = main}
- (void)viewDidLoad {
    [super viewDidLoad];
    
    NSOperationQueue *queue = [NSOperationQueue new];
    
    NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"blockOperationWithBlock1---%@", [NSThread currentThread]);
        sleep(1.0);
    }];
    
    NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"blockOperationWithBlock2---%@", [NSThread currentThread]);
        sleep(2.0);
    }];
    
    NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"blockOperationWithBlock3---%@", [NSThread currentThread]);
        sleep(3.0);
    }];
    
    [queue addOperation:operation1];
    [queue addOperation:operation2];
    [queue addOperation:operation3];
    
    // 会阻塞当前线程
    [queue waitUntilAllOperationsAreFinished];
    NSLog(@"所有操作都已执行完成---%@", [NSThread currentThread]);
}

// 打印
17:34:04.224280+0800 Demo[1979:24709361] blockOperationWithBlock3---<NSThread: 0x6000013b4c00>{number = 5, name = (null)}
17:34:04.224284+0800 Demo[1979:24709359] blockOperationWithBlock1---<NSThread: 0x600001389100>{number = 6, name = (null)}
17:34:04.224280+0800 Demo[1979:24709365] blockOperationWithBlock2---<NSThread: 0x600001381ec0>{number = 7, name = (null)}
17:34:07.225338+0800 Demo[1979:24709300] 所有操作都已执行完成---<NSThread: 0x6000013f50c0>{number = 1, name = main}

4,监听操作的执行过程

- (void)viewDidLoad {
    [super viewDidLoad];
    
    NSOperationQueue *queue = [NSOperationQueue new];
    
    NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"blockOperationWithBlock1---%@", [NSThread currentThread]);
    }];
    
    NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"blockOperationWithBlock2---%@", [NSThread currentThread]);
    }];
    
    [operation1 addObserver:self
                forKeyPath:@"ready"
                   options:NSKeyValueObservingOptionNew
                   context:nil];
    [operation1 addObserver:self
                forKeyPath:@"executing"
                   options:NSKeyValueObservingOptionNew
                   context:nil];
    [operation1 addObserver:self
                forKeyPath:@"finished"
                   options:NSKeyValueObservingOptionNew
                   context:nil];
    
    [operation1 addDependency:operation2];
    [queue addOperation:operation1];
    [queue addOperation:operation2];
}

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary<NSKeyValueChangeKey,id> *)change
                       context:(void *)context {
    BOOL status = [change[NSKeyValueChangeNewKey] boolValue];
    if ([keyPath isEqualToString:@"ready"]) {
        if (status) {
            NSLog(@"operation1已准备好");
        } else {
            NSLog(@"operation1未准备好");
        }
    } else if ([keyPath isEqualToString:@"executing"]) {
        if (status) {
            NSLog(@"operation1正在执行");
        } else {
            NSLog(@"operation1停止执行");
        }
    } else if ([keyPath isEqualToString:@"finished"]) {
        if (status) {
            NSLog(@"operation1已执行完成");
        } else {
            NSLog(@"operation1未执行完成");
        }
    }
}

// 打印
operation1未准备好
blockOperationWithBlock2---<NSThread: 0x600002aae900>{number = 6, name = (null)}
operation1已准备好
operation1正在执行
blockOperationWithBlock1---<NSThread: 0x600002abb780>{number = 4, name = (null)}
operation1停止执行
operation1已执行完成

5,线程通信

- (void)viewDidLoad {
    [super viewDidLoad];
 
    NSOperationQueue *queue = [NSOperationQueue new];
    NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
    
    [queue addOperationWithBlock:^{
        NSLog(@"在子线程请求数据---%@", [NSThread currentThread]);

        [mainQueue addOperationWithBlock:^{
            NSLog(@"回主线程刷新UI---%@", [NSThread currentThread]);
        }];
    }];
}

// 打印
在子线程请求数据---<NSThread: 0x6000032d4540>{number = 7, name = (null)}
回主线程刷新UI---<NSThread: 0x6000032a6140>{number = 1, name = main}
六,自定义NSOperation

1,非并发:只需实现main方法即可

// YJCustomOperation.h
@interface YJCustomOperation : NSOperation
- (instancetype)initWithBlock:(void(^)(void))block;
@end

// YJCustomOperation.m
@interface YJCustomOperation ()
@property (nonatomic, copy) void(^block)(void);
@end

@implementation YJCustomOperation
- (instancetype)initWithBlock:(void(^)(void))block {
    self = [super init];
    if (self) {
        self.block = block;
    }
    return self;
}
- (void)main {
    // 在此方法中无法访问主线程的自动释放池,所以需要手动创建
    @autoreleasepool {
        // 响应取消事件
        if (self.isCancelled) return;
        // 执行任务
        if (self.block) {
            self.block();
        }
    }
}
@end

// 使用
- (void)viewDidLoad {
    [super viewDidLoad];
    
    YJCustomOperation *operation = [[YJCustomOperation alloc] initWithBlock:^{
        NSLog(@"initWithBlock---%@", [NSThread currentThread]);
    }];
    [operation start];
}

// 打印
initWithBlock---<NSThread: 0x600002254b40>{number = 1, name = main}

2,并发:需要实现startexecutingfinishedasynchronous方法

// YJCustomOperation.h
@interface YJCustomOperation : NSOperation
- (instancetype)initWithBlock:(void(^)(void))block;
@end

// YJCustomOperation.m
@interface YJCustomOperation ()
@property (nonatomic, readwrite, getter=isExecuting) BOOL executing;
@property (nonatomic, readwrite, getter=isFinished) BOOL finished;
@property (nonatomic, copy) void(^block)(void);
@end

@implementation YJCustomOperation
@synthesize executing = _executing;
@synthesize finished = _finished;

- (instancetype)initWithBlock:(void(^)(void))block {
    self = [super init];
    if (self) {
        self.block = block;
    }
    return self;
}

- (void)start {
    @autoreleasepool {
        self.executing = YES;

        if (self.isCancelled) {
            self.executing = NO;
            self.finished = YES;
            return;
        };
        
        if (self.block) {
            self.block();
        }
        
        self.executing = NO;
        self.finished = YES;
    }
}

- (void)setExecuting:(BOOL)executing {
    if (_executing != executing) {
        // 手动发送KVO通知
        [self willChangeValueForKey:@"executing"];
        _executing = executing;
        [self didChangeValueForKey:@"executing"];
    }
}

- (void)setFinished:(BOOL)finished {
    if (_finished != finished) {
        [self willChangeValueForKey:@"finished"];
        _finished = finished;
        [self didChangeValueForKey:@"finished"];
    }
}

- (BOOL)isExecuting {
    return _executing;
}

- (BOOL)isFinished {
    return _finished;
}

// 是否并发
- (BOOL)isAsynchronous {
    return YES;
}
@end

// 使用
- (void)viewDidLoad {
    [super viewDidLoad];
    
    NSOperationQueue *queue = [NSOperationQueue new];
    
    YJCustomOperation *operation = [[YJCustomOperation alloc] initWithBlock:^{
        NSLog(@"initWithBlock---%@", [NSThread currentThread]);
    }];

    [queue addOperation:operation];
}

// 打印
initWithBlock---<NSThread: 0x600000b3dc80>{number = 6, name = (null)}
上一篇下一篇

猜你喜欢

热点阅读