iOS 멀티스레드 NSOperation의 기본 사용

27224 단어
1. NSOperation, NSOperationQueue 소개
NSOperation, NSOperationQueue는 애플이 우리에게 제공한 다중 루틴 해결 방안이다.실제로 NSOperation, NSOperationQueue는 GCD를 기반으로 한 한층 더 높은 패키지로 대상을 대상으로 한다.그러나 GCD보다 간단하고 사용하기 쉬우며 코드의 가독성도 높다.
NSOperation NSoperationQueue를 사용하는 이유
1. 작업이 끝난 후에 완전한 코드 블록을 추가할 수 있습니다
2. 조작 간의 의존 관계를 추가하여 편리한 제어 실행 순서
3. 작업 실행 우선 순위 설정
4. 한 조작의 실행을 쉽게 취소할 수 있다
5. KVO를 사용하여 작업 수행 상태의 변경 사항을 관찰: isExecuteing, isFinished, isCancelled
2 NSOperation NSOperationQueue 작업 및 작업 대기열
GCD 기반의 한 단계 더 높은 패키지인 이상그러면 GCD의 일부 개념은 NSOperation, NSOperationQueue에도 적용된다.NSoperation과 NSOperationQUeue에서도 유사한 작업(작업)과 대기열(작업 대기열)의 개념이 있다.
조작하다
실행 조작의 뜻은 바꾸어 말하면 네가 라인에서 실행한 그 코드이다
GCD에서는 Block에 배치되어 실행됩니다.NSoperation에서는 NSOperation 하위 클래스 NSInvocation Operation, NSBlockOperation 또는 하위 클래스를 사용하여 작업을 캡슐화합니다.
작업 대기열
여기의 대기열은 작업 대기열을 저장하는 데 사용되는 대기열이 GCD의 스케줄링 대기열인 FIFO(선진 선출)와 다르다는 원칙을 가리킨다. NSOperationQueue는 대기열에 추가된 작업에 대해 먼저 준비 상태에 들어간다. (준비 상태는 작업 간의 의존 관계에 달려 있다).그런 다음 준비 상태에 들어간 작업의 시작 실행 순서(비종료 실행 순서)는 작업 간의 상대적인 우선 순위에 의해 결정됩니다(우선 순위는 작업 객체 자체의 속성).
작업 대기열은 최대 병렬 작업 수 (maxConcurrentOperationCount) 를 설정해서 병렬, 직렬을 제어합니다.
NSOperationQueue는 홈 및 사용자 정의 대기열과 같은 두 가지 유형의 대기열을 제공합니다.홈 대기열은 메인 라인 위에서 실행되고, 사용자 정의 대기열은 백엔드에서 실행됩니다.
3 NSOperation NSOperationQueue 사용 단계
NSOperation은 NSOperationQueue와 함께 멀티스레드를 구현해야 합니다.기본적으로 NSOperation이 단독으로 사용될 때 시스템이 동기화하기 때문에 NSOperationQueue와 함께 비동기적으로 실행할 수 있습니다.
NSOperation의 멀티스레드 사용 단계는 3단계로 구성됩니다.
1. 작업 만들기: 먼저 수행해야 할 작업을 NSOperation 객체로 캡슐화합니다.
2. 대기열 만들기: NSOperationQueue 객체 만들기
3. 대기열에 작업 추가: NSOperation 객체를 NSOperationQueue 객체에 추가
그러면 NSOperationQueue의 NSOperation이 자동으로 제거되어 새 스레드에서 작업이 수행됩니다.
4 NSOperation 사용
NSOPerationQueue에 추가하지 않고 캡슐화할 때
- (void)blockOPeration {
    NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"op1 --- %@",[NSThread currentThread]);
    }];
    NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"op2 --- %@",[NSThread currentThread]);
    }];
    NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"op3 --- %@",[NSThread currentThread]);
    }];
    
    //    
    /*
     *                                      (      1)         
     NSInvocationOperation
*/ [op3 addExecutionBlock:^{ NSLog(@"op4 ---- %@",[NSThread currentThread]); }]; [op3 addExecutionBlock:^{ NSLog(@"op5 ---- %@",[NSThread currentThread]); }]; [op3 addExecutionBlock:^{ NSLog(@"op6 ---- %@",[NSThread currentThread]); }]; [op1 start]; [op2 start]; [op3 start]; }
2018-03-08 23:05:43.358904+0800 NSOperationDemo[899:52772] op1 --- {number = 1, name = main}
2018-03-08 23:05:43.359121+0800 NSOperationDemo[899:52772] op2 --- {number = 1, name = main}
2018-03-08 23:05:43.359699+0800 NSOperationDemo[899:52772] op5 ---- {number = 1, name = main}
2018-03-08 23:05:43.359701+0800 NSOperationDemo[899:52966] op3 --- {number = 3, name = (null)}
2018-03-08 23:05:43.359714+0800 NSOperationDemo[899:53301] op4 ---- {number = 4, name = (null)}
2018-03-08 23:05:43.359719+0800 NSOperationDemo[899:53306] op6 ---- {number = 5, name = (null)}

NSOperationQueue 사용
- (void)invocationOPerationWithQueue {
    //         
    //           self
    //             
    //                 
    NSInvocationOperation *operation1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(task1) object:nil];
    NSInvocationOperation *operation2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(task2) object:nil];
    NSInvocationOperation *operation3 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(task3) object:nil];
    //    
    /*
     GCD
          crate &    
          create &       
     NSOperation:
         [NSOperationQueue mainQueue];      
          [[NSOperationQueue alloc] init];                   
                      
               (maxConcurrentOperationCount)     、  
     maxConcurrentOperationCount = 1                      
     */
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    [queue addOperation:operation1];//       Start  
    [queue addOperation:operation2];
    [queue addOperation:operation3];
}

- (void)task1 {
    NSLog(@"task1  %@",[NSThread currentThread]);
}
- (void)task2 {
    NSLog(@"task2  %@",[NSThread currentThread]);
}
- (void)task3 {
    NSLog(@"task3  %@",[NSThread currentThread]);
}

NSBlockOperation 사용
- (void)blockOPerationWithQueue {
    NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"op1 --- %@",[NSThread currentThread]);
    }];
    NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"op2 --- %@",[NSThread currentThread]);
    }];
    NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"op3 --- %@",[NSThread currentThread]);
    }];
    //    
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    [queue addOperation:op1];
    [queue addOperation:op2];
    [queue addOperation:op3];
}
//    
 [queue addOperationWithBlock:^{
        NSLog(@"op4 ---- %@",[NSThread currentThread]);
 }];

NSOperation 사용자 지정
임무에 적용되는 방대한 코드가 비교적 복잡하기 때문에 임무를 추출하여 쓰면 코드 은폐에 유리하고 코드의 복용성을 높일 수 있다
#import "LFOperation.h"

@implementation LFOperation
//           
- (void)main {
    NSLog(@"main --- %@",[NSThread currentThread]);
}

@end
viewController
- (void)lfoperation {
    LFOperation *op1 = [[LFOperation alloc] init];
    LFOperation *op2 = [[LFOperation alloc] init];
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    [queue addOperation:op1];
    [queue addOperation:op2];
}

기타 용법
최대 동시 발생
//               
- (void)test {
    //    
    //       
    self.queue = [[NSOperationQueue alloc] init];
    //       (                )             1       (       )                       
    //                 -1      
    self.queue.maxConcurrentOperationCount = 1;
    //    
    NSOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"op1---  %@",[NSThread currentThread]);
    }];
    NSOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"op2---  %@",[NSThread currentThread]);
    }];
    NSOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"op3---  %@",[NSThread currentThread]);
    }];
    NSOperation *op4 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"op4---  %@",[NSThread currentThread]);
    }];
    NSOperation *op5 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"op5---  %@",[NSThread currentThread]);
    }];
    NSOperation *op6 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"op6---  %@",[NSThread currentThread]);
    }];
    
    [self.queue addOperation:op1];
    [self.queue addOperation:op2];
    [self.queue addOperation:op3];
    [self.queue addOperation:op4];
    [self.queue addOperation:op5];
    [self.queue addOperation:op6];
    
}

일시 중지 취소 시작 계속
- (IBAction)start:(id)sender {
    //    
    //       
    self.queue = [[NSOperationQueue alloc] init];
    self.queue.maxConcurrentOperationCount = 1;
    //    
    NSOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
        for (NSInteger i = 0; i < 10000; i ++) {
            NSLog(@"op1---  %@",[NSThread currentThread]);
        }
        
    }];
    NSOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
        for (NSInteger i = 0; i < 10000; i ++) {
            NSLog(@"op2---  %@",[NSThread currentThread]);
        }
        
    }];
    NSOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
        for (NSInteger i = 0; i < 10000; i ++) {
            NSLog(@"op3---  %@",[NSThread currentThread]);
        }
        
    }];
    [self.queue addOperation:op1];
    [self.queue addOperation:op2];
    [self.queue addOperation:op3];
}


- (IBAction)pause:(id)sender {
    //                                                   
    //            
    /*
           |       |          
     */
    [self.queue setSuspended:YES];
}

- (IBAction)goon:(id)sender {
    [self.queue setSuspended:NO];
}

- (IBAction)cancel:(id)sender {
    //                                            cancel  
    [self.queue cancelAllOperations];
}

그러나main 함수에 사용자 정의로 적힌 동작은 여러 개라도 하나의 작업으로 여겨지기 때문에 일시 정지 취소 계속은 효과가 없지만 취소 작업이 효과가 있다고 판단할 수 있습니다 취소에만 한정됩니다
//           
- (void)main {
    
    for (NSInteger i = 0; i < 10000; i ++) {
        NSLog(@"op1---  %@",[NSThread currentThread]);
    }
    if (self.isCancelled) {
        return;
    }
    
    for (NSInteger i = 0; i < 10000; i ++) {
        NSLog(@"op2---  %@",[NSThread currentThread]);
    }
    if (self.isCancelled) {
        return;
    }
    for (NSInteger i = 0; i < 10000; i ++) {
        NSLog(@"op3---  %@",[NSThread currentThread]);
    }
}

NSOperation 작업 종속 및 스니퍼 추가
의지하다
- (void)yilai {
    //    
    //       
    self.queue = [[NSOperationQueue alloc] init];
    //    
    NSOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"op1---  %@",[NSThread currentThread]);
    }];
    NSOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"op2---  %@",[NSThread currentThread]);
    }];
    NSOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"op3---  %@",[NSThread currentThread]);
    }];
    NSOperation *op4 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"op4---  %@",[NSThread currentThread]);
    }];
    //      
    //                                   
    //                   (     )
    [op1 addDependency:op4];//         4    4       
    [op4 addDependency:op3];
    [op3 addDependency:op2];
    [self.queue addOperation:op1];
    [self.queue addOperation:op2];
    [self.queue addOperation:op3];
    [self.queue addOperation:op4];
}

모니터
- (void)jianting {
    //    
    //       
    self.queue = [[NSOperationQueue alloc] init];
    //    
    NSOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"op1---  %@",[NSThread currentThread]);
    }];
    NSOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"op2---  %@",[NSThread currentThread]);
    }];
    NSOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"op3---  %@",[NSThread currentThread]);
    }];
    NSOperation *op4 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"op4---  %@",[NSThread currentThread]);
    }];
    //    
    op3.completionBlock = ^{
        NSLog(@"op3      %@",[NSThread currentThread]);
    };
    
    //      
    //                                   
    //                   (     )
    [op1 addDependency:op4];//         4    4       
    [op4 addDependency:op3];
    [op3 addDependency:op2];
    [self.queue addOperation:op1];
    [self.queue addOperation:op2];
    [self.queue addOperation:op3];
    [self.queue addOperation:op4];

스레드 간 통신
- (void)downLoadImage {
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    NSOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
        NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"&&&&&"]];
        NSData *data = [NSData dataWithContentsOfURL:url];
        UIImage *image = [UIImage imageWithData:data];
        //     UI
        [NSOperationQueue.mainQueue addOperationWithBlock:^{
            self.imageView.image = image;
        }];
        
    }];
    [queue addOperation:op1];
}

좋은 웹페이지 즐겨찾기