NSOperation簡(jiǎn)介

  • 配合使用NSOperation和NSOperationQueue也能實(shí)現(xiàn)多線程編程
    • NSOperation是個(gè)抽象類,并不具備封裝操作的能力,必須使用它的子類
      • NSInvocationOperation
      • NSBlockOperation
      • 自定義子類繼承NSOperation,實(shí)現(xiàn)內(nèi)部相應(yīng)的main方法
    • NSOperationQueue的作用
      • NSOperation可以調(diào)用start方法來執(zhí)行任務(wù),但默認(rèn)是同步執(zhí)行的
      • 如果將NSOperation添加到NSOperationQueue(操作隊(duì)列)中,系統(tǒng)會(huì)自動(dòng)異步執(zhí)行NSOperation中的操作
        • 添加方法1:- (void)addOperation:(NSOperation *)op;
        • 添加方法2:- (void)addOperationWithBlock:(void (^)(void))block;
  • 使用NSInvocationOperation實(shí)現(xiàn)多線程編程
    • 步驟:
      • 封裝操作 initWithTarget
      • 實(shí)現(xiàn)操作對(duì)應(yīng)的方法 sel
      • 啟動(dòng)操作 start
    • 注意
      • 默認(rèn)情況下,調(diào)用了start方法后并不會(huì)開一條新線程去執(zhí)行操作,而是在當(dāng)前線程同步執(zhí)行操作
      • 只有將NSOperation放到一個(gè)NSOperationQueue中,才會(huì)異步執(zhí)行操作
  • 使用NSBlockOperation實(shí)現(xiàn)多線程編程
    • 步驟:
      • 封裝操作 blockOperationWithBlock
      • 追加操作 addExecutionBlock:(此步驟可以省略,即可以追加操作也可以不追加操作)
      • 啟動(dòng)操作 start
    • 注意
      • 只要NSBlockOperation封裝的操作數(shù)>1,就會(huì)異步執(zhí)行操作
      • 即只有追加操作,才會(huì)異步執(zhí)行操作
  • 自定義子類繼承NSOperation,實(shí)現(xiàn)內(nèi)部相應(yīng)的main方法
    • 創(chuàng)建自定義的子類繼承NSOperation
    • 在子類中實(shí)現(xiàn)內(nèi)部相應(yīng)的main方法
      • 自己創(chuàng)建自動(dòng)釋放池(因?yàn)槿绻钱惒讲僮鳎瑹o法訪問主線程的自動(dòng)釋放池)
      • 經(jīng)常通過-(BOOL)isCancelled方法檢測(cè)操作是否被取消,對(duì)取消做出響應(yīng)
    • 實(shí)例化子類對(duì)象,并實(shí)現(xiàn)操作
  • 使用NSInvocationOperation和NSOperationQueue實(shí)現(xiàn)多線程編程
    • 步驟
      • 封裝操作
      • 創(chuàng)建隊(duì)列
        • 主隊(duì)列mainQueue(凡是在主隊(duì)列中的任務(wù)都在主線程中執(zhí)行&串行隊(duì)列)
        • 非主隊(duì)列[[NSOperationQueue alloc]init](同時(shí)具備了并發(fā)和串行的功能,默認(rèn)是并發(fā)隊(duì)列)
      • 把操作添加到隊(duì)列中
        • addOperation:
        • addOperationWithBlock:
  • 并發(fā)數(shù)
    • 概念:同時(shí)執(zhí)行的任務(wù)數(shù)
    • 必須在操作添加到隊(duì)列之前設(shè)置最大并發(fā)數(shù)的個(gè)數(shù)
    • 最大并發(fā)數(shù)的方法
        • (NSInteger)maxConcurrentOperationCount;
        • (void)setMaxConcurrentOperationCount:(NSInteger)cnt;
    • 最大并發(fā)數(shù)量
      • maxConcurrentOperationCount = 1 串行隊(duì)列
      • maxConcurrentOperationCount > 1 并發(fā)隊(duì)列
      • maxConcurrentOperationCount = -1 并發(fā)數(shù)不做限制,并發(fā)隊(duì)列
      • maxConcurrentOperationCount = 0 程序不能運(yùn)行
  • 同步執(zhí)行任務(wù)的情況
    • 僅使用NSInvocationOperation
    • 僅使用NSBlockOperation
    • 使用NSOperation和mainQueue
    • 使用NSOperation和[[NSOperationQueue alloc]init]且最大并發(fā)數(shù)為0
  • 隊(duì)列的暫停、恢復(fù)、取消
    • 隊(duì)列的暫停
      • -(void)setSuspended:(BOOL)b; // YES代表暫停隊(duì)列,NO代表恢復(fù)隊(duì)列
      • -(BOOL)isSuspended;
      • 不能暫停當(dāng)前處于執(zhí)行狀態(tài)的操作
      • 只能停止后面沒有處于執(zhí)行狀態(tài)的操作
      • 暫停操作是可以恢復(fù)的
    • 隊(duì)列的恢復(fù)
      • -(void)setSuspended:(BOOL)b; // YES代表暫停隊(duì)列,NO代表恢復(fù)隊(duì)列
      • -(BOOL)isSuspended;
    • 隊(duì)列的取消
      • 取消所有隊(duì)列的操作-(void)cancelAllOperations;,內(nèi)部調(diào)用每個(gè)操作的cancel方法
      • 調(diào)用NSOperation的- (void)cancel方法取消單個(gè)操作
      • 后面的任務(wù)將永遠(yuǎn)沒有機(jī)會(huì)執(zhí)行
      • 取消操作是不能恢復(fù)的
    • 實(shí)現(xiàn)步驟
      • 在storyboard中拖拽開始執(zhí)行、暫停、取消、恢復(fù)4個(gè)按鈕
      • 生成其對(duì)應(yīng)的點(diǎn)擊事件的方法
      • 開始執(zhí)行方法
        • 使用NSBlockOperation封裝操作
        • 創(chuàng)建隊(duì)列
        • 設(shè)置最大并發(fā)數(shù)為1(保證程序串行執(zhí)行)
        • 把操作添加到隊(duì)列
      • 暫停方法
        • 設(shè)置isSuspended屬性為YES
      • 取消方法
        • 調(diào)用cancelAllOperations方法
      • 恢復(fù)方法
        • 設(shè)置isSuspended屬性為NO
    • 實(shí)現(xiàn)代碼
@interface ViewController ()

/** 隊(duì)列 */
@property(nonatomic, strong)NSOperationQueue *queue;

@end

@implementation ViewController
/**
 *  開始執(zhí)行
 */
- (IBAction)startBtnClick {

    // 創(chuàng)建操作對(duì)象
    NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
        for (int i = 0; i < 10000; i++) {
            NSLog(@"1---%zd---main------%@", i,[NSThread currentThread]);
        }
    }];
    NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
        for (int i = 0; i < 10000; i++) {
            NSLog(@"2---%zd---main------%@", i,[NSThread currentThread]);
        }
    }];
    NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
        for (int i = 0; i < 10000; i++) {
            NSLog(@"3---%zd---main------%@", i,[NSThread currentThread]);
        }
    }];

    // 創(chuàng)建隊(duì)列
    self.queue = [[NSOperationQueue alloc] init];

    // 設(shè)置最大并發(fā)數(shù)
    self.queue.maxConcurrentOperationCount = 1;

    // 把操作添加到隊(duì)列
    [self.queue addOperation:op1];
    [self.queue addOperation:op2];
    [self.queue addOperation:op3];
}

/**
 *  暫停
 */
- (IBAction)suspendBtnClick {

    [self.queue setSuspended:YES];
}

/**
 *  取消
 */
- (IBAction)cancleBtnClick {

    [self.queue cancelAllOperations];
}

/**
 *  恢復(fù)
 */
- (IBAction)resumeBtnClick {

    [self.queue setSuspended:NO];
}

@end
  • 自定義NSOperatioin子類實(shí)現(xiàn)隊(duì)列的取消
    • 自定義NSOperatioin子類
    • 重寫main方法
    • 在storyboard中拖拽開始執(zhí)行、取消2個(gè)按鈕
      • 生成其對(duì)應(yīng)的點(diǎn)擊事件的方法
      • 開始執(zhí)行方法
        • 使用自定義NSOperatioin子類封裝操作
        • 創(chuàng)建隊(duì)列
        • 設(shè)置最大并發(fā)數(shù)為1(保證程序串行執(zhí)行)
        • 把操作添加到隊(duì)列
      • 取消方法
        • 調(diào)用cancelAllOperations方法
    • 代碼實(shí)現(xiàn)
// 控制器代碼
@interface ViewController ()

/** 隊(duì)列 */
@property(nonatomic, strong)NSOperationQueue *queue;

@end

@implementation ViewController

- (IBAction)startBtnClick {

    // 封裝操作
    ZQOperation *op = [[ZQOperation alloc] init];

    // 創(chuàng)建隊(duì)列
    self.queue = [[NSOperationQueue alloc] init];

    // 設(shè)置最大并發(fā)數(shù)
    self.queue.maxConcurrentOperationCount = 1;

    // 把操作添加到隊(duì)列
    [self.queue addOperation:op];

}

- (IBAction)cancelBtnClick {

    [self.queue cancelAllOperations];
}
@end
  • 操作的依賴、監(jiān)聽

    • 操作的依賴
      • NSOperation之間可以設(shè)置依賴來保證執(zhí)行順序
      • 可以在不同queue的NSOperation之間創(chuàng)建依賴關(guān)系
      • [operationB addDependency:operationA]; // 操作B依賴于操作A
      • 不能設(shè)置循環(huán)依賴:A依賴B,B依賴A
      • 設(shè)置依賴必須再把操作添加到隊(duì)列之前
    • 操作的監(jiān)聽
      • -(void (^)(void))completionBlock;
      • -(void)setCompletionBlock:(void (^)(void))block;
      • 當(dāng)要實(shí)現(xiàn)在A操作完成后實(shí)現(xiàn)B操作時(shí)需要監(jiān)聽A操作
  • NSOperation實(shí)現(xiàn)線程間的通信(下載兩張圖片并合成)

    • 思路
      • 封裝下載圖片1操作download1
      • 封裝下載圖片2操作download2
      • 封裝合成圖片操作combie(繪圖)
      • 創(chuàng)建隊(duì)列
      • 設(shè)置操作依賴
      • 把操作添加到隊(duì)列中
    • 代碼實(shí)現(xiàn)
    /** 下載兩張圖片并合成 */
    -(void)combieDownloadPicture{
    
    __block UIImage *image1;
    __block UIImage *image2;
    // 封裝下載圖片1操作
    NSBlockOperation *download1 = [NSBlockOperation blockOperationWithBlock:^{
        NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://pic14.nipic.com/20110522/7411759_164157418126_2.jpg"]];
        image1 = [UIImage imageWithData:data];
    }];
    
    // 封裝下載圖片2操作
    NSBlockOperation *download2 = [NSBlockOperation blockOperationWithBlock:^{
        NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://pic28.nipic.com/20130402/9252150_190139450381_2.jpg"]];
        image2 = [UIImage imageWithData:data];
    }];
    
    // 封裝合成圖片操作
    NSBlockOperation *combie = [NSBlockOperation blockOperationWithBlock:^{
        // 獲取圖形上下文
        UIGraphicsBeginImageContext(CGSizeMake(240, 240));
    
        // 畫圖1
        [image1 drawInRect:CGRectMake(0, 0, 240, 120)];
    
        // 畫圖2
        [image2 drawInRect:CGRectMake(0, 120, 240, 120)];
    
        // 生成圖片
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    
        // 關(guān)閉圖形上下文
        UIGraphicsEndImageContext();
    
        // 回到主線程刷新UI
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            self.imageView.image = image;
        }];
    }];
    
    // 創(chuàng)建隊(duì)列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    
    // 設(shè)置依賴
    [combie addDependency:download1];
    [combie addDependency:download2];
    
    // 把操作添加到隊(duì)列中
    [queue addOperation:download1];
    [queue addOperation:download2];
    [queue addOperation:combie];
    

}

```
最后編輯于
?著作權(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)容