iOS開發(fā)之多線程—NSOperation<五>

一、簡(jiǎn)介

NSOperation是蘋果提供給我們的一套多線程解決方案。實(shí)際上NSOperation是基于GCD更高一層的封裝,但是比GCD更簡(jiǎn)單易用、代碼可讀性也更高。


NSOperation需要配合NSOperationQueue來實(shí)現(xiàn)多線程。因?yàn)槟J(rèn)情況下,NSOperation單獨(dú)使用時(shí)系統(tǒng)同步執(zhí)行操作,并沒有開辟新線程的能力,只有配合NSOperationQueue才能實(shí)現(xiàn)異步執(zhí)行。

NSOperation實(shí)現(xiàn)多線程的使用步驟分為三步:

  1. 創(chuàng)建任務(wù):先將需要執(zhí)行的操作封裝到一個(gè)NSOperation對(duì)象中。
  2. 創(chuàng)建隊(duì)列:創(chuàng)建NSOperationQueue對(duì)象。
  3. 將任務(wù)加入到隊(duì)列中:然后將NSOperation對(duì)象添加到NSOperationQueue中。

二、使用

1、創(chuàng)建任務(wù)

NSOperation是個(gè)抽象類,并不能封裝任務(wù)。我們只有使用它的子類來封裝任務(wù)。我們有三種方式來封裝任務(wù)。

使用子類NSInvocationOperation
使用子類NSBlockOperation
定義繼承自NSOperation的子類,通過實(shí)現(xiàn)內(nèi)部相應(yīng)的方法來封裝任務(wù)。
在不使用NSOperationQueue,單獨(dú)使用NSOperation的情況下系統(tǒng)同步執(zhí)行操作,下面我們學(xué)習(xí)以下任務(wù)的三種創(chuàng)建方式。

//1.使用子類NSInvocationOperation
- (void)NSInvocationOperationUse{
    //在沒有使用NSOperationQueue、單獨(dú)使用NSInvocationOperation的情況下,NSInvocationOperation在主線程執(zhí)行操作,并沒有開啟新線程。
    //1.創(chuàng)建NSInvocationOperation對(duì)象
    NSInvocationOperation *op = [[NSInvocationOperation alloc]initWithTarget:self selector:(@selector(runOp)) object:nil];
    //2.開始執(zhí)行操作
    [op start];
}
- (void)runOp{
    NSLog(@"runOp------%@",[NSThread currentThread]);
}
運(yùn)行結(jié)果
//2.使用子類NSBlockOperationUse
- (void)NSBlockOperationUse{
    //NSBlockOperation提供了一個(gè)方法addExecutionBlock:,通過addExecutionBlock:就可以為NSBlockOperation添加額外的操作,這些額外的操作就會(huì)在其他線程并發(fā)執(zhí)行。
    //1.創(chuàng)建NSBlockOperation對(duì)象
    NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
        //主線程
        NSLog(@"NSBlockOperationUse------%@",[NSThread currentThread]);

    }];
    // 添加額外的任務(wù)(在子線程執(zhí)行)
    [op addExecutionBlock:^{
        NSLog(@"2------%@", [NSThread currentThread]);
    }];
    [op addExecutionBlock:^{
        NSLog(@"3------%@", [NSThread currentThread]);
    }];
    [op addExecutionBlock:^{
        NSLog(@"4------%@", [NSThread currentThread]);
    }];

    //2.開始執(zhí)行操作
    [op start];
}
運(yùn)行結(jié)果
//3.定義繼承自NSOperation的子類
- (void)NSOperationUse{
    //主線程
    ZQNSOperation *op = [[ZQNSOperation alloc]init];

    [op start];
}

//ZQNSOperation.h
#import <Foundation/Foundation.h>
@interface ZQNSOperation : NSOperation

@end

//ZQNSOperation.m 重新main方法
#import "ZQNSOperation.h"
@implementation ZQNSOperation
- (void)main{
    //任務(wù)
    for (int i = 0; i < 2; ++i) {
        NSLog(@"1-----%@",[NSThread currentThread]);
    }
}
@end
運(yùn)行結(jié)果
2.創(chuàng)建隊(duì)列

和GCD中的并發(fā)隊(duì)列、串行隊(duì)列略有不同的是:NSOperationQueue一共有兩種隊(duì)列:主隊(duì)列、其他隊(duì)列。其中其他隊(duì)列同時(shí)包含了串行、并發(fā)功能。下邊是主隊(duì)列、其他隊(duì)列的基本創(chuàng)建方法和特點(diǎn)。

主隊(duì)列
凡是添加到主隊(duì)列中的任務(wù)(NSOperation),都會(huì)放到主線程中執(zhí)行

NSOperationQueue *queue = [NSOperationQueue mainQueue];

其他隊(duì)列(非主隊(duì)列)
添加到這種隊(duì)列中的任務(wù)(NSOperation),就會(huì)自動(dòng)放到子線程中執(zhí)行
同時(shí)包含了:串行、并發(fā)功能

NSOperationQueue *queue = [[NSOperationQueue alloc] init];
3.將任務(wù)添加到隊(duì)列
- (void)NSInvocationOperationUse{

    //1.創(chuàng)建NSInvocationOperation對(duì)象
    NSInvocationOperation *op = [[NSInvocationOperation alloc]initWithTarget:self selector:(@selector(runOp)) object:nil];
    //2.創(chuàng)建NSBlockOperation
    NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
        for (int i = 0; i < 2; ++i) {
            NSLog(@"1-----%@", [NSThread currentThread]);
        }
    }];
    //創(chuàng)建隊(duì)列
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    //2.開始執(zhí)行操作
    [queue addOperation:op];
    [queue addOperation:op2];
}
- (void)runOp{
    NSLog(@"runOp------%@",[NSThread currentThread]);
}
運(yùn)行結(jié)果

可以直接在block中添加任務(wù),無需先創(chuàng)建

    //創(chuàng)建隊(duì)列
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    //添加操作到隊(duì)列中
    [queue addOperationWithBlock:^{
        for (int i = 0; i < 2; ++i) {
            NSLog(@"-----%@", [NSThread currentThread]);
        }
    }];
運(yùn)行結(jié)果
4.串行 并行

最大并發(fā)數(shù):maxConcurrentOperationCount
maxConcurrentOperationCount默認(rèn)情況下為-1,表示不進(jìn)行限制,默認(rèn)為并發(fā)執(zhí)行。
當(dāng)maxConcurrentOperationCount為1時(shí),進(jìn)行串行執(zhí)行,開啟1條子線程。

當(dāng)maxConcurrentOperationCount大于1時(shí),進(jìn)行并發(fā)執(zhí)行,當(dāng)然這個(gè)值不應(yīng)超過系統(tǒng)限制,即使自己設(shè)置一個(gè)很大的值,系統(tǒng)也會(huì)自動(dòng)調(diào)整。
maxConcurrentOperationCount為0,不執(zhí)行隊(duì)列任務(wù)。

 //創(chuàng)建隊(duì)列
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    //設(shè)置maxConcurrentOperationCount
    queue.maxConcurrentOperationCount = 2;
    //添加任務(wù)
    [queue addOperationWithBlock:^{
        NSLog(@"1-----%@", [NSThread currentThread]);

    }];
    [queue addOperationWithBlock:^{
        NSLog(@"2-----%@", [NSThread currentThread]);
        
    }];
    [queue addOperationWithBlock:^{
        NSLog(@"3-----%@", [NSThread currentThread]);
        
    }];
    [queue addOperationWithBlock:^{
        NSLog(@"4-----%@", [NSThread currentThread]);
        
    }];
    [queue addOperationWithBlock:^{
        NSLog(@"5-----%@", [NSThread currentThread]);
        
    }];

運(yùn)行結(jié)果
5.操作依賴

比如說有A、B兩個(gè)操作,其中A執(zhí)行完操作,B才能執(zhí)行操作,那么就需要讓B依賴于A。

//創(chuàng)建隊(duì)列
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    
    NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"1-----%@", [NSThread  currentThread]);
    }];
    NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"2-----%@", [NSThread  currentThread]);
    }];
    
    [op2 addDependency:op1];    //添加依賴關(guān)系,op2依賴于op1
    
    [queue addOperation:op1];
    [queue addOperation:op2];

運(yùn)行結(jié)果
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容