iOS多線程開發(fā)之NSOperation用法總結(jié)

NSOperation的作用

配合使用NSOperation和NSOperationQueue也能實(shí)現(xiàn)多線程編程

NSOperation和NSOperationQueue實(shí)現(xiàn)多線程的具體步驟

  • 先將需要執(zhí)行的操作封裝到一個(gè)NSOperation對(duì)象中
  • 然后將NSOperation對(duì)象添加到NSOperationQueue中
  • 系統(tǒng)會(huì)自動(dòng)將NSOperationQueue中的NSOperation取出來
  • 將取出的NSOperation封裝的操作放到一條新線程中執(zhí)行

注意:

  • NSOperation是個(gè)抽象類,并不具備封裝操作的能力河咽,必須使用它的子類
  • 使用NSOperation子類的方式有3種:
  • NSInvocationOperation
  • NSBlockOperation
  • 自定義子類繼承NSOperation牵啦,實(shí)現(xiàn)內(nèi)部相應(yīng)的方法

NSInvocationOperation類

  • 創(chuàng)建NSInvocationOperation對(duì)象
-(id)initWithTarget:(id)targetselector:(SEL)selobject:(id)arg;
  • 調(diào)用start方法開始執(zhí)行操作
-(void)start;

一旦執(zhí)行操作挺举,就會(huì)調(diào)用target的sel方法

  • 代碼:
NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil];
    [op start];
 - (void)run
{
    NSLog(@"------%@", [NSThread currentThread]);
}
  • 注意:
  • 默認(rèn)情況下汹粤,調(diào)用了start方法后并不會(huì)開一條新線程去執(zhí)行操作箩做,而是在當(dāng)前線程同步執(zhí)行操作
  • 只有將NSOperation放到一個(gè)NSOperationQueue中虫腋,才會(huì)異步執(zhí)行操作
  • 此類僅當(dāng)了解骄酗,在開發(fā)中并不常用

NSBlockOperation類

  • 創(chuàng)建NSBlockOperation對(duì)象
+(id)blockOperationWithBlock:(void(^)(void))block;
  • 通過addExecutionBlock:方法添加更多的操作
-(void)addExecutionBlock:(void(^)(void))block;
  • 代碼:
 NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
        // 在主線程
        NSLog(@"下載1------%@", [NSThread currentThread]);
    }];
    
    // 添加額外的任務(wù)(在子線程執(zhí)行)
    [op addExecutionBlock:^{
        NSLog(@"下載2------%@", [NSThread currentThread]);
    }];
    [op addExecutionBlock:^{
        NSLog(@"下載3------%@", [NSThread currentThread]);
    }];
    [op addExecutionBlock:^{
        NSLog(@"下載4------%@", [NSThread currentThread]);
    }];
    
    [op start];
  • 注意:只要NSBlockOperation封裝的操作數(shù) >1,就會(huì)異步執(zhí)行操作

NSOperationQueue

  • NSOperationQueue的作用

  • NSOperation可以調(diào)用start方法來執(zhí)行任務(wù)悦冀,但默認(rèn)是同步執(zhí)行的

  • 如果將NSOperation添加到NSOperationQueue(操作隊(duì)列)中趋翻,系統(tǒng)會(huì)自動(dòng)異步執(zhí)行NSOperation中的操作

  • 添加操作到NSOperationQueue中

-(void)addOperation:(NSOperation*)op;
-(void)addOperationWithBlock:(void(^)(void))block;
  • 代碼:
  • 方法一:
    // 創(chuàng)建隊(duì)列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    
    // 創(chuàng)建操作
        NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"download1 --- %@", [NSThread currentThread]);
        }];
    
    //添加操作到隊(duì)列中
        [queue addOperation:op1];
  • 方法二:
 // 創(chuàng)建隊(duì)列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//添加操作到隊(duì)列中
 [queue addOperationWithBlock:^{
        NSLog(@"download1 --- %@", [NSThread currentThread]);
    }];

NSOperationQueue的隊(duì)列類型與GCD的隊(duì)列類型對(duì)比

  • GCD的隊(duì)列
  • 并發(fā)隊(duì)列
    • 自己創(chuàng)建的
    • 全局
  • 串行隊(duì)列
    • 主隊(duì)列
    • 自己創(chuàng)建的
  • NSOperationQueue的隊(duì)列
  • 主隊(duì)列
    [NSOperationQueue mainQueue]
 - 凡是添加到主隊(duì)列中的任務(wù)(NSOperation),都會(huì)放到主線程中執(zhí)行
  • 非主隊(duì)列(其他隊(duì)列)
     [[NSOperationQueue alloc] init]
 - 同時(shí)包含了:串行盒蟆、并發(fā)功能
 - 添加到這種隊(duì)列中的任務(wù)(NSOperation)踏烙,就會(huì)自動(dòng)放到子線程中執(zhí)行

最大并發(fā)數(shù)

  • 什么是并發(fā)數(shù)

  • 同時(shí)執(zhí)行的任務(wù)數(shù)

  • 比如,同時(shí)開3個(gè)線程執(zhí)行3個(gè)任務(wù)历等,并發(fā)數(shù)就是3

  • 最大并發(fā)數(shù)的相關(guān)方法

-(NSInteger)maxConcurrentOperationCount;
-(void)setMaxConcurrentOperationCount:(NSInteger)cnt;
  • 代碼
     // 創(chuàng)建隊(duì)列
     NSOperationQueue *queue = [[NSOperationQueue alloc] init]; 
     // 設(shè)置最大并發(fā)操作數(shù)
     // queue.maxConcurrentOperationCount = 2;// 并發(fā)隊(duì)列
     queue.maxConcurrentOperationCount = 1; // 就變成了串行隊(duì)列
     // 添加操作
     [queue addOperationWithBlock:^{
          NSLog(@"download1 --- %@", [NSThread currentThread])
      }];
     [queue addOperationWithBlock:^{
          NSLog(@"download2 --- %@", [NSThread currentThread])
      }];
     [queue addOperationWithBlock:^{
          NSLog(@"download3 --- %@", [NSThread currentThread])
      }];
    
    

隊(duì)列的取消讨惩、暫停、恢復(fù)

  • 取消隊(duì)列的所有操作
-(void)cancelAllOperations;

提示:也可以調(diào)用NSOperation的-(void)cancel方法取消單個(gè)操作

  • 暫停和恢復(fù)隊(duì)列
  -(void)setSuspended:(BOOL)b;// YES代表暫停隊(duì)列寒屯,NO代表恢復(fù)隊(duì)列
  - (BOOL)isSuspended
  • 代碼
 // 恢復(fù)隊(duì)列荐捻,繼續(xù)執(zhí)行
 // self.queue.suspended = NO;

 // 暫停(掛起)隊(duì)列,暫停執(zhí)行
 // self.queue.suspended = YES;

 // 取消隊(duì)列的所有操作
 [self.queue cancelAllOperations];

操作依賴

  • NSOperation之間可以設(shè)置依賴來保證執(zhí)行順序
  • 比如一定要讓操作A執(zhí)行完后寡夹,才能執(zhí)行操作B处面,可以這么寫
[operationB addDependency:operationA];// 操作B依賴于操作A
  • 也可以在不同queue的NSOperation之間創(chuàng)建依賴關(guān)系
  • 代碼
    // 創(chuàng)建隊(duì)列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    // 添加操作
    NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"download1----%@", [NSThread  currentThread]);
    }];
    NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"download2----%@", [NSThread  currentThread]);
    }];
    NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"download3----%@", [NSThread  currentThread]);
    }];
   // 設(shè)置依賴(保證op3在op1和op2都執(zhí)行完之后再執(zhí)行)
    [op3 addDependency:op1];
    [op3 addDependency:op2];
  • 注意:不能相互依賴
  • 比如A依賴B,B依賴A

線程之間的通信

  • 舉例:在子線程下載圖片菩掏,再回答到主線程在imageView添加圖片
  • 看代碼:
   [[[NSOperationQueue alloc] init] addOperationWithBlock:^{
        // 圖片的網(wǎng)絡(luò)路徑
        NSURL *url = [NSURL URLWithString:@"http://img.pconline.com.cn/images/photoblog/9/9/8/1/9981681/200910/11/1255259355826.jpg"];
        
        // 加載圖片
        NSData *data = [NSData dataWithContentsOfURL:url];
        
        // 生成圖片
        UIImage *image = [UIImage imageWithData:data];
        
        // 回到主線程
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            self.imageView.image = image;
        }];
    }];

操作的監(jiān)聽

  • 可以監(jiān)聽一個(gè)操作的執(zhí)行完畢
-(void(^)(void))completionBlock;
-(void)setCompletionBlock:(void(^)(void))block;

自定義NSOperation

  • 自定義NSOperation的步驟很簡(jiǎn)單
  • 重寫-(void)main方法魂角,在里面實(shí)現(xiàn)想執(zhí)行的任務(wù)
  • 重寫-(void)main方法的注意點(diǎn)
  • 自己創(chuàng)建自動(dòng)釋放池(因?yàn)槿绻钱惒讲僮鳎瑹o(wú)法訪問主線程的自動(dòng)釋放池)
  • 經(jīng)常通過-(BOOL)isCancelled方法檢測(cè)操作是否被取消智绸,對(duì)取消做出響應(yīng)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末野揪,一起剝皮案震驚了整個(gè)濱河市访忿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌囱挑,老刑警劉巖醉顽,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異平挑,居然都是意外死亡游添,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門通熄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來唆涝,“玉大人,你說我怎么就攤上這事唇辨±群ǎ” “怎么了?”我有些...
    開封第一講書人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵赏枚,是天一觀的道長(zhǎng)亡驰。 經(jīng)常有香客問我,道長(zhǎng)饿幅,這世上最難降的妖魔是什么凡辱? 我笑而不...
    開封第一講書人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮栗恩,結(jié)果婚禮上透乾,老公的妹妹穿的比我還像新娘。我一直安慰自己磕秤,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開白布市咆。 她就那樣靜靜地躺著汉操,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蒙兰。 梳的紋絲不亂的頭發(fā)上客情,一...
    開封第一講書人閱讀 49,031評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音癞己,去河邊找鬼。 笑死梭伐,一個(gè)胖子當(dāng)著我的面吹牛痹雅,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播糊识,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼绩社,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼摔蓝!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起愉耙,我...
    開封第一講書人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤贮尉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后朴沿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體猜谚,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年赌渣,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了魏铅。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡坚芜,死狀恐怖览芳,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情鸿竖,我是刑警寧澤沧竟,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站缚忧,受9級(jí)特大地震影響悟泵,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜搔谴,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一魁袜、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧敦第,春花似錦峰弹、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至右钾,卻和暖如春蚁吝,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背舀射。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工窘茁, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人脆烟。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓山林,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親邢羔。 傳聞我的和親對(duì)象是個(gè)殘疾皇子驼抹,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

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

  • NSThread 第一種:通過NSThread的對(duì)象方法 NSThread *thread = [[NSThrea...
    攻城獅GG閱讀 789評(píng)論 0 3
  • 在這篇文章中桑孩,我將為你整理一下 iOS 開發(fā)中幾種多線程方案,以及其使用方法和注意事項(xiàng)框冀。當(dāng)然也會(huì)給出幾種多線程的案...
    張戰(zhàn)威ican閱讀 601評(píng)論 0 0
  • 多線程基本概念 單核CPU流椒,同一時(shí)間cpu只能處理1個(gè)線程,只有1個(gè)線程在執(zhí)行 。多線程同時(shí)執(zhí)行:是CPU快速的在...
    WeiHing閱讀 699評(píng)論 1 5
  • 世界上最可怕的事是當(dāng)我長(zhǎng)大之后你已經(jīng)老去~ 1 曾經(jīng)報(bào)名參加了學(xué)校一個(gè)訪問孤寡老人的志愿活動(dòng)明也,地點(diǎn)是廈門...
    小小薰閱讀 623評(píng)論 0 0
  • 當(dāng)我一個(gè)人躺在床上的時(shí)候,很大一部分感覺帆吻,不是空虛域那,也不是寂寞。而是一種叫做迷茫的感覺猜煮。 就像一個(gè)浪人漂泊在海上次员。...
    陳丶胡子閱讀 276評(píng)論 0 0