認(rèn)識和使用NSOperation

NSOperation是OC中多線程技術(shù)的一種,是對GCD的OC包裝.它包含隊列(NSOperationQueue)操作(NSOperation)兩個基本要素.

通過這篇文章你可以了解到:

  • 怎樣使用NSOperation
  • 怎樣使用NSOperationQueue
  • 如何給NSOperationQueue設(shè)置并發(fā)數(shù)
  • NSOperationQueue的暫停恢復(fù)和取消
  • 通過添加依賴影響操作的執(zhí)行順序
  • NSOperation的進程間通信

怎樣使用NSOperation

  • NSOperation本身是一個抽象類,要使用可以通過以下幾個辦法:
    • 使用NSInvocationOperation
    • 使用NSBlockOperation
    • 自定義NSOperation的子類

使用

  • NSInvocationOperation
NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(task) object:nil];
// 調(diào)用start方法執(zhí)行操作op操作
[op start];
  • NSBlockOperation
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"task0---%@", [NSThread currentThread]);
}];
[op start];

根據(jù)打印的結(jié)果我們會發(fā)現(xiàn),直接調(diào)用start方法時,系統(tǒng)并不會開辟一個新的線程去執(zhí)行任務(wù),任務(wù)會在當(dāng)前線程同步執(zhí)行.

注意: 這里我們說的是當(dāng)前線程而非主線程,意即:如果是在主線程中調(diào)用op的start方法,那么該任務(wù)是在主線程中執(zhí)行;但如果是在其他子線程調(diào)用start方法,任務(wù)則是在其他子線程執(zhí)行.

當(dāng)然NSBlockOperation還有一種使用方法addExecutionBlock:使得我們可以給其添加更多的操作,使用如下:

NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"task0---%@", [NSThread currentThread]);
}];

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

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

// 開始必須在添加其他操作之后
[op start];

由打印的結(jié)果發(fā)現(xiàn): task0的結(jié)果和前面的結(jié)論一樣,是執(zhí)行在主線程中的(因為是在主線程中調(diào)用start方法),但task1和task2都是在自己的新線程中執(zhí)行.也就是說:當(dāng)NSBlockOperation封裝的操作數(shù)大于1的時候,就會執(zhí)行異步操作.

  • 自定義NSOperation

自定義NSOperation的方法也很簡單,我們需要做到下面幾個步驟:

1.子類化NSOperation

2.在.m文件里面實現(xiàn)-(void)main方法

3.初始化該操作的時候直接調(diào)用alloc及init即可

4.同樣可以通過start方法讓你自定義的任務(wù)跑在當(dāng)前線程中

關(guān)鍵代碼:

自定義NSOperation的實現(xiàn)文件:

#import "AROperation.h"
@implementation AROperation
- (void)main {
    NSLog(@"this is my custom operation ---- %@", [NSThread currentThread]);
}
@end

使用(在任何需要啟用該任務(wù)的地方):

// 該操作被執(zhí)行時就會執(zhí)行op內(nèi)部定義的任務(wù)
AROperation *op = [[AROperation alloc] init];
[op start];

怎樣使用NSOperationQueue

NSOperation的start方法默認(rèn)是同步執(zhí)行任務(wù),這樣的使用并不多見,只有將NSOperation與NSOperationQueue進行結(jié)合,才會發(fā)揮出這種多線程技術(shù)的最大功效.當(dāng)NSOperation被添加到NSOperationQueue中后,就會全自動地執(zhí)行異步操作.

  • NSOperationQueue的種類:

    • 自帶主隊列[NSOperationQueue mainQueue]: 添加到主隊列中的任務(wù)都會在主線程中執(zhí)行
    • 自己創(chuàng)建隊列(非主隊列)
      NSOperationQueue *queue = [[NSOperationQueue alloc] init];: 這種隊列同時包含串行息罗、并發(fā)的功能,添加到非主隊列的任務(wù)會自動放到子線程中執(zhí)行
  • 向NSOperationQueue中添加操作:

    • 直接添加
      [queue addOperation:op1];
    • 使用block添加,block的內(nèi)容會被包裝成operation對象添加到隊列
      [queue addOperationWithBlock:^{ }];
      操作一但被到添加到隊列中,就會自動異步執(zhí)行.

設(shè)置NSOperationQueue的最大并發(fā)數(shù)

NSOperationQueue可以通過以下方法設(shè)置最大并發(fā)數(shù),
setMaxConcurrentOperationCount:,值得注意的是:**當(dāng)并發(fā)數(shù)為1就變成了串行執(zhí)行任務(wù)
**

NSOperationQueue的暫偷嘀洌恢復(fù)和取消

  • 取消
    • NSOperation有一個cancel方法可以取消單個操作
    • NSOperationQueue的cancelAllOperations相當(dāng)于隊列中的每個operation調(diào)用了cancel方法,會取消隊列里面全部的操作.
    • 但是,不能取消正在進行中的任務(wù),隊列調(diào)用了cancelAllOperations后會等當(dāng)前正在進行的任務(wù)執(zhí)行完閉后取消后面的操作
  • 掛起和恢復(fù)
    • isSuspended : 判斷是否掛起
    • setSuspended: YES表示掛起,NO表示恢復(fù)
    • 和取消功能類似,我們同樣不能掛起正在運行中的操作,隊列會等當(dāng)前操作結(jié)束后將后面的操作暫停(掛起)

因此, 我們在自定義NSOperation的時候需要注意,最好可以經(jīng)常通過判斷isCancelled方法檢測操作是否被取消,以響應(yīng)外部可能進行的取消操作.如:

// 自定義NSOperation類.m文件的main方法實現(xiàn)
- (void)main {
    for (NSInteger i = 0; i < 1000; i++) {
        NSLog(@"SubTask---0---%zd",i);
    }
    // 判斷當(dāng)前任務(wù)是否被取消,如果已經(jīng)取消,及時返回
    if (self.cancelled) {
        return;
    }

    for (NSInteger i = 0; i < 1000; i++) {

        NSLog(@"SubTask---1---%zd", i);
    }
    if (self.cancelled) {
        return;
    }

    for (NSInteger i = 0; i < 1000; i++) {
        NSLog(@"SubTask---2---%zd",i);
    }
}

添加依賴和監(jiān)聽

  • 通過設(shè)置操作間的依賴,可以確定這些操作的執(zhí)行順序
    如:
[op3 addDependency:op1];
[op3 addDependency:op2];

表示op3會在op1和op2都執(zhí)行完畢后才執(zhí)行

添加依賴的時候要注意防止添加循環(huán)依賴,此外我們還可以在不同隊列的operation之間添加依賴

  • 監(jiān)聽
    • op.completeBlock可以監(jiān)聽一個操作執(zhí)行完畢的時刻,這個block里面可以添加一些我們需要執(zhí)行的操作
    • 這個block里面的操作仍然是在子線程執(zhí)行,但不一定和被監(jiān)聽的操作在同一個線程

線程間通信

有時我們在子線程中執(zhí)行完一些操作的時候,需要回到主線程做一些事情(如進行UI操作),因此需要從當(dāng)前線程回到主線程,以下載并顯示圖片為例,方法如下:

NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 子線程下載圖片
[queue addOperationWithBlock:^{
    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 alloc] initWithData:data];
    // 回到主線程進行顯示
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        self.imageView.image = image;
    }];
}];

NSOperation的使用還是比較簡單的,但是要注意的細(xì)節(jié)比較多,一些方法比較容易被忽略,于是乎特此總結(jié)一下.這里就不上傳示例代碼了,有問題的童鞋可以直接留言.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市绍刮,隨后出現(xiàn)的幾起案子温圆,更是在濱河造成了極大的恐慌,老刑警劉巖录淡,帶你破解...
    沈念sama閱讀 221,576評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件捌木,死亡現(xiàn)場離奇詭異,居然都是意外死亡嫉戚,警方通過查閱死者的電腦和手機刨裆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來彬檀,“玉大人帆啃,你說我怎么就攤上這事∏系郏” “怎么了努潘?”我有些...
    開封第一講書人閱讀 168,017評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長坤学。 經(jīng)常有香客問我疯坤,道長,這世上最難降的妖魔是什么深浮? 我笑而不...
    開封第一講書人閱讀 59,626評論 1 296
  • 正文 為了忘掉前任压怠,我火速辦了婚禮,結(jié)果婚禮上飞苇,老公的妹妹穿的比我還像新娘菌瘫。我一直安慰自己,他們只是感情好布卡,可當(dāng)我...
    茶點故事閱讀 68,625評論 6 397
  • 文/花漫 我一把揭開白布雨让。 她就那樣靜靜地躺著,像睡著了一般忿等。 火紅的嫁衣襯著肌膚如雪栖忠。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,255評論 1 308
  • 那天这弧,我揣著相機與錄音娃闲,去河邊找鬼。 笑死匾浪,一個胖子當(dāng)著我的面吹牛皇帮,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蛋辈,決...
    沈念sama閱讀 40,825評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼属拾,長吁一口氣:“原來是場噩夢啊……” “哼将谊!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起渐白,我...
    開封第一講書人閱讀 39,729評論 0 276
  • 序言:老撾萬榮一對情侶失蹤尊浓,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后纯衍,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體栋齿,經(jīng)...
    沈念sama閱讀 46,271評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,363評論 3 340
  • 正文 我和宋清朗相戀三年襟诸,在試婚紗的時候發(fā)現(xiàn)自己被綠了瓦堵。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,498評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡歌亲,死狀恐怖菇用,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情陷揪,我是刑警寧澤惋鸥,帶...
    沈念sama閱讀 36,183評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站悍缠,受9級特大地震影響卦绣,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜飞蚓,卻給世界環(huán)境...
    茶點故事閱讀 41,867評論 3 333
  • 文/蒙蒙 一迎卤、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧玷坠,春花似錦、人聲如沸劲藐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽聘芜。三九已至兄渺,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間汰现,已是汗流浹背挂谍。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留瞎饲,地道東北人口叙。 一個月前我還...
    沈念sama閱讀 48,906評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像嗅战,于是被迫代替她去往敵國和親妄田。 傳聞我的和親對象是個殘疾皇子俺亮,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,507評論 2 359

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