NSOperation&&NSOperationQueue

NSOperation&&NSOperationQueue

簡介

NSOperation袱讹、NSOperationQueue 是蘋果提供給我們的一套多線程解決方案。實際上 NSOperation席镀、NSOperationQueue 是基于 GCD 更高一層的封裝,完全面向?qū)ο蟆5潜?GCD 更簡單易用、代碼可讀性也更高颊咬。

NSOperation&NSOperationQueue--操作和操作隊列

既然是基于 GCD 的更高一層的封裝。那么牡辽,GCD 中的一些概念同樣適用于 NSOperation、NSOperationQueue敞临。在 NSOperation态辛、NSOperationQueue 中也有類似的任務(wù)(操作)隊列(操作隊列)的概念。

  • 操作(Operation):

    • 要執(zhí)行的任務(wù)挺尿,GCD中放在Block中的任務(wù)

    • 在NSOperation中奏黑,我們使用我們使用NSOperation子類NSInvocationOperation、NSBlockOperation或者自定義子類來封裝操作编矾。

  • 操作隊列(NSOperationQueue):

    • 操作隊列即用來存放操作的隊列熟史。不同于GCD中的調(diào)度隊列FIFO(先進先出)的原則

    • 操作隊列通過設(shè)置最大并發(fā)操作數(shù)maxConcurrentOperationCount來控制同一時間執(zhí)行任務(wù)的數(shù)量,從而達到控制并發(fā)窄俏、串行蹂匹,并不是來控制線程的多少,當并發(fā)數(shù)為1的時候就是順序執(zhí)行,大于1的時候并發(fā)執(zhí)行凹蜈,順序不確定(默認并發(fā)數(shù)-1限寞,沒有并發(fā)限制)

    • NSOperationQueue為我們提供了2種不同類型的隊列:主隊列和自定義隊列。主隊列運行在主線程之上仰坦,自定義隊列在后臺執(zhí)行履植。

NSOperation&&NSOperationQueue實現(xiàn)多線程步驟:

1.創(chuàng)建任務(wù):先將需要執(zhí)行的操作封裝到NSOperation對象中。

2.創(chuàng)建隊列:創(chuàng)建NSOperationQueue悄晃。

3.添加任務(wù)到隊列中:將NSOperation對象添加到NSOperationQueue中玫霎。

NSOperation三種創(chuàng)建方式

NSOperation是個抽象類,實際運用時中需要使用它的子類妈橄,有三種方式:

1.使用子類NSInvocationOperation

2.使用子類NSBlockOperation

3.定義繼承自NSOperation的子類

  • 子類NSInvocationOperation(很少使用)
    //創(chuàng)建操作
    NSInvocationOperation *invocationOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(Task:) object:nil];
    //start方法開始執(zhí)行操作(同步操作沒有開啟線程)
    [invocationOperation start];

-(void)Task:(id)objec{
    NSLog(@"operaton:%@",[NSThread currentThread]);
}
Output
    //創(chuàng)建隊列
    NSOperationQueue *operationQueue = [[NSOperationQueue alloc]init];
    //創(chuàng)建操作
    NSInvocationOperation *invocationOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(Task:) object:nil];
    //將操作添加到隊列中自動異步執(zhí)行局(新線程)
    [operationQueue addOperation:invocationOperation];

-(void)Task:(id)objec{
    NSLog(@"operaton:%@",[NSThread currentThread]);
}
Output

總結(jié):

單獨使用NSOperationQueue執(zhí)行任務(wù)是同步執(zhí)行任務(wù)的(沒有開啟新的線程)庶近,將操作添加到操作隊列中自動異步執(zhí)行

  • 子類NSBlockOperation
    1.Block初始化操作
    NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"TaskA:%@",[NSThread currentThread]);
    }];
    [blockOperation addExecutionBlock:^{
        NSLog(@"TaskB:%@",[NSThread currentThread]);
    }];
    [blockOperation addExecutionBlock:^{
        NSLog(@"TaskC:%@",[NSThread currentThread]);
    }];
    [blockOperation addExecutionBlock:^{
        NSLog(@"TaskD:%@",[NSThread currentThread]);
    }];
    [blockOperation addExecutionBlock:^{
        NSLog(@"TaskE:%@",[NSThread currentThread]);
    }];
    [blockOperation addExecutionBlock:^{
        NSLog(@"TaskF:%@",[NSThread currentThread]);
    }];
    [blockOperation start];

屏幕快照 2019-08-20 下午2.58.27.png
2.alloc初始化操作

    NSBlockOperation *blockOperation = [[NSBlockOperation alloc]init];
    [blockOperation addExecutionBlock:^{
        NSLog(@"TaskB:%@",[NSThread currentThread]);
    }];
    [blockOperation addExecutionBlock:^{
        NSLog(@"TaskC:%@",[NSThread currentThread]);
    }];
    [blockOperation addExecutionBlock:^{
        NSLog(@"TaskD:%@",[NSThread currentThread]);
    }];
    [blockOperation addExecutionBlock:^{
        NSLog(@"TaskE:%@",[NSThread currentThread]);
    }];
    [blockOperation addExecutionBlock:^{
        NSLog(@"TaskF:%@",[NSThread currentThread]);
    }];
    [blockOperation start];

屏幕快照 2019-08-20 下午3.17.21.png
3.操作添加到操作隊列中執(zhí)行

   //創(chuàng)建任務(wù)
   NSBlockOperation *blockOperationA = [NSBlockOperation blockOperationWithBlock:^{
       NSLog(@"TaskA:%@",[NSThread currentThread]);
   }];
   NSBlockOperation *blockOperationB = [NSBlockOperation blockOperationWithBlock:^{
       NSLog(@"TaskB:%@",[NSThread currentThread]);
   }];
   NSBlockOperation *blockOperationC = [NSBlockOperation blockOperationWithBlock:^{
       NSLog(@"TaskC:%@",[NSThread currentThread]);
   }];
   NSBlockOperation *blockOperationD = [NSBlockOperation blockOperationWithBlock:^{
       NSLog(@"TaskD:%@",[NSThread currentThread]);
   }];
   
   //添加隊列
   NSOperationQueue *operationQueue = [[NSOperationQueue alloc]init];
   [operationQueue addOperation:blockOperationA];
   [operationQueue addOperation:blockOperationB];
   [operationQueue addOperation:blockOperationC];
   [operationQueue addOperation:blockOperationD];
   [operationQueue addOperationWithBlock:^{
       NSLog(@"TaskE:%@",[NSThread currentThread]);
   }];
屏幕快照 2019-08-20 下午3.36.51.png

總結(jié):
1.非操作隊列管理:無論是blockOperationWithBlock初始化的操作還是[[NSBlockOperation alloc]init]初始化的操作,當操作任務(wù)數(shù)量為1的時候同步執(zhí)行眷细,當前線程執(zhí)行任務(wù)拦盹,當操作/任務(wù)數(shù)量大于1的時候,所有的任務(wù)溪椎,包括初始化第一個block任務(wù)普舆,都可以異步執(zhí)行恬口。(可以異步執(zhí)行不是一定異步執(zhí)行,每個任務(wù)任務(wù)都有可能在當前線程或者新線程執(zhí)行沼侣,具體由系統(tǒng)決定)
2.操作隊列管理:操作添加到隊列后自動異步執(zhí)行祖能,開啟新線程

  • 自定義NSOperation子類

NSOperationQueue操作隊列

  • 操作隊列類型
    NSOperationQueue 一共有兩種隊列:主隊列、自定義隊列蛾洛。其中自定義隊列同時包含了串行养铸、并發(fā)功能。
    //主隊列
    NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
    //自定義隊列
    NSOperationQueue *concurrentQueue = [[NSOperationQueue alloc]init];
  • 操作隊列添加任務(wù)
- (void)addOperation:(NSOperation *)operation;
  • 操作依賴
    NSOperation之間可以通過設(shè)置依賴來管理任務(wù)的執(zhí)行順序(不能相互依賴轧膘,比如A依賴B钞螟,B依賴A)
    [blockOperationB addDependency:blockOperationA];
  • 操作隊列控制任務(wù)串行并發(fā)

1.主隊列任務(wù)串行執(zhí)行
2.自定義隊列通過控制最大任務(wù)并發(fā)數(shù)來控制任務(wù)串行并發(fā),maxConcurrentOperationCount=1串行執(zhí)行谎碍,maxConcurrentOperationCount大于1鳞滨,或者默認值,并發(fā)執(zhí)行

NSOperation與GCD對比

  • GCD是純C語言的API蟆淀,NSOperationQueue是基于GCD的OC版本封裝拯啦,GCD執(zhí)行效率更高
  • GCD只支持FIFO的隊列,NSOperationQueue可以很方便地調(diào)整執(zhí)行順序熔任、設(shè)置最大并發(fā)數(shù)量
  • 依賴關(guān)系:NSOperationQueue可以在輕松在Operation間設(shè)置依賴關(guān)系褒链,而GCD需要寫很多的代碼才能實現(xiàn)(dispatch_barrier_async來實現(xiàn))
  • KVO:NSOperationQueue支持KVO,可以監(jiān)測operation是否正在執(zhí)行(isExecuted)疑苔、是否結(jié)束(isFinished)甫匹,是否取消(isCanceld)

操作&&操作隊列多線程總結(jié):

屏幕快照 2019-08-21 上午10.52.39.png
  • 隊列中操作的執(zhí)行順序:
    添加到隊列中的操作執(zhí)行順序由maxConcurrentOperationCount最大操作并發(fā)數(shù)決定,同時受操作依賴影響
  • 隊列中操作開啟線程情況:
    添加到隊列中的操作開啟了新線程執(zhí)行(具體數(shù)量系統(tǒng)決定)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末夯巷,一起剝皮案震驚了整個濱河市赛惩,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌趁餐,老刑警劉巖喷兼,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異后雷,居然都是意外死亡季惯,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門臀突,熙熙樓的掌柜王于貴愁眉苦臉地迎上來勉抓,“玉大人,你說我怎么就攤上這事候学∨航睿” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵梳码,是天一觀的道長隐圾。 經(jīng)常有香客問我伍掀,道長,這世上最難降的妖魔是什么暇藏? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任蜜笤,我火速辦了婚禮,結(jié)果婚禮上盐碱,老公的妹妹穿的比我還像新娘把兔。我一直安慰自己,他們只是感情好瓮顽,可當我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布县好。 她就那樣靜靜地躺著,像睡著了一般趣倾。 火紅的嫁衣襯著肌膚如雪聘惦。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天儒恋,我揣著相機與錄音,去河邊找鬼黔漂。 笑死诫尽,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的炬守。 我是一名探鬼主播牧嫉,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼减途!你這毒婦竟也來了酣藻?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤鳍置,失蹤者是張志新(化名)和其女友劉穎辽剧,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體税产,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡怕轿,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了辟拷。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片撞羽。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖衫冻,靈堂內(nèi)的尸體忽然破棺而出诀紊,到底是詐尸還是另有隱情,我是刑警寧澤隅俘,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布邻奠,位于F島的核電站笤喳,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏惕澎。R本人自食惡果不足惜莉测,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望唧喉。 院中可真熱鬧捣卤,春花似錦、人聲如沸八孝。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽干跛。三九已至子姜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間楼入,已是汗流浹背哥捕。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留嘉熊,地道東北人遥赚。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像阐肤,于是被迫代替她去往敵國和親凫佛。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,901評論 2 345

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