多線程NSOperation 與 GCD的區(qū)別

Mac OS X 10.6及iOS4.0之后導(dǎo)入了可以使全體線程更高效運行幅慌,并且使并行處理應(yīng)用更易開發(fā)的架構(gòu)辫秧,GCD(Grand Central? Dispatch)担锤,同時引入的還有Run Loop,線程(包括Cocoa和POSIX)和Operation儿礼。GCD擁有非常輕量級的工作單元和并發(fā)方式咖杂,并且由系統(tǒng)決定其最佳調(diào)度方式。這個時候出現(xiàn)了一個問題蚊夫,NSOperation如何處理呢诉字?

其實我們在通過NSOperation和GCD進行開發(fā)過程中,會發(fā)現(xiàn)兩者執(zhí)行的方式有許多相似之處知纷,NSOperation和GCD參照對比壤圃,NSOperationQueue和dispatch_queue參照對比,但是兩者之間還是有許多差別的琅轧,具體區(qū)別:

1.GCD的核心是C語言寫的系統(tǒng)服務(wù)伍绳,執(zhí)行和操作簡單高效,因此NSOperation底層也通過GCD實現(xiàn)乍桂,換個說法就是NSOperation是對GCD更高層次的抽象冲杀,這是他們之間最本質(zhì)的區(qū)別.因此如果希望自定義任務(wù)效床,建議使用NSOperation;

2.依賴關(guān)系权谁,NSOperation可以設(shè)置兩個NSOperation之間的依賴剩檀,第二個任務(wù)依賴于第一個任務(wù)完成執(zhí)行,GCD無法設(shè)置依賴關(guān)系旺芽,不過可以通過dispatch_barrier_async來實現(xiàn)這種效果谨朝;

3.KVO(鍵值對觀察),NSOperation和容易判斷Operation當前的狀態(tài)(是否執(zhí)行甥绿,是否取消),對此GCD無法通過KVO進行判斷则披;

4.優(yōu)先級共缕,NSOperation可以設(shè)置自身的優(yōu)先級士复,但是優(yōu)先級高的不一定先執(zhí)行图谷,GCD只能設(shè)置隊列的優(yōu)先級,無法在執(zhí)行的block設(shè)置優(yōu)先級阱洪;

5.繼承便贵,NSOperation是一個抽象類實際開發(fā)中常用的兩個類是NSInvocationOperation和NSBlockOperation,同樣我們可以自定義NSOperation冗荸,GCD執(zhí)行任務(wù)可以自由組裝承璃,沒有繼承那么高的代碼復(fù)用度;

6.效率蚌本,直接使用GCD效率確實會更高效盔粹,NSOperation會多一點開銷,但是通過NSOperation可以獲得依賴程癌,優(yōu)先級舷嗡,繼承,鍵值對觀察這些優(yōu)勢嵌莉,相對于多的那么一點開銷確實很劃算进萄,魚和熊掌不可得兼,取舍在于開發(fā)者自己锐峭;

關(guān)于主要的區(qū)別都已經(jīng)總結(jié)中鼠,根據(jù)實際開發(fā)中來說,GCD使用情況較多只祠,簡單高效兜蠕,從變成原則上來看,應(yīng)該是使用高層次的抽象抛寝,避免使用低層次的抽象熊杨,那么無疑我們應(yīng)該選擇NSOperation曙旭,因為復(fù)雜的任務(wù)可以自己通過NSOperation實現(xiàn),日常還是GCD的天下晶府,畢竟GCD有更高的并發(fā)和執(zhí)行能力


NSOperation是蘋果封裝的一套多線程的東西桂躏,不像GCD是純C語言的,這個是OC的川陆。但相比較之下GCD會更快一些剂习,但本質(zhì)上NSOPeration是多GDC的封裝。

一较沪、NSOperation與GCD的比較

GCD是基于c的底層api鳞绕,NSOperation屬于object-c類。ios首先引入的是NSOperation尸曼,IOS4之后引入了GCD和NSOperationQueue并且其內(nèi)部是用gcd實現(xiàn)的们何。

GCD優(yōu)點:GCD主要與block結(jié)合使用。代碼簡潔高效控轿。執(zhí)行效率稍微高點冤竹。

NSOperation相對于GCD

1,NSOperation擁有更多的函數(shù)可用茬射,具體查看api鹦蠕。NSOperationQueue 是在GCD基礎(chǔ)上實現(xiàn)的,只不過是GCD更高一層的抽象在抛。

2钟病,在NSOperationQueue中,可以建立各個NSOperation之間的依賴關(guān)系霜定。

3档悠,NSOperationQueue支持KVO⊥疲可以監(jiān)測operation是否正在執(zhí)行(isExecuted)辖所、是否結(jié)束(isFinished),是否取消(isCanceld)

4磨德,GCD 只支持FIFO 的隊列缘回,而NSOperationQueue可以調(diào)整隊列的執(zhí)行順序(通過調(diào)整權(quán)重)。NSOperationQueue可以方便的管理并發(fā)典挑、NSOperation之間的優(yōu)先級酥宴。

使用NSOperation的情況:各個操作之間有依賴關(guān)系、操作需要取消暫停您觉、并發(fā)管理拙寡、控制操作之間優(yōu)先級,限制同時能執(zhí)行的線程數(shù)量.讓線程在某時刻停止/繼續(xù)等琳水。

使用GCD的情況:一般的需求很簡單的多線程操作肆糕,用GCD都可以了般堆,簡單高效。

從編程原則來說诚啃,一般我們需要盡可能的使用高等級淮摔、封裝完美的API,在必須時才使用底層API始赎。

當需求簡單和橙,簡潔的GCD或許是個更好的選擇,而Operation queue 為我們提供能更多的選擇造垛。

二魔招、NSOperation的簡單操作

?NSOperation(操作)配NSoperationQueue(隊列)來實現(xiàn)多線程.

?沒有像GCD一樣串行并行什么的,直接拿來就能用.

?操作依賴:NSOperation可以通過設(shè)置依賴來保證執(zhí)行順序.某一個操作的執(zhí)行, 必須等待另一個操作完成才會繼續(xù)執(zhí)行.

使用:[op1addDependency:op2] ?依賴關(guān)系可以跨隊列指定的.(不能弄成循環(huán)依賴)

?可以指定隊列的優(yōu)先級。

使用NSOperation的方法(3者是等價的):(注意NSOperation是抽象類,

必須使用他的子類才能實現(xiàn))

?方法1五辽、用NSOperation的子類NSInvocationOperation來創(chuàng)建操作.

?方法2仆百、用NSOperation的子類NSBlockOperation來創(chuàng)建操作.?(與前者效果一樣)

?方法3、直接弄個隊列(可以是主隊列,先跑起來),再addOperationWithBlock更加簡便.

?方法4奔脐、直接自定義NSOperation,實現(xiàn)相應(yīng)的方法吁讨。

實現(xiàn)NSOperation的方法髓迎,以及掛起、暫停建丧,設(shè)置最大并發(fā)數(shù)排龄,設(shè)置依賴關(guān)系等

[objc]view

plaincopy

@interfaceXNViewController?()

/**?NSOperation操作隊列?*/

@property(nonatomic,strong)NSOperationQueue*queue;

@end

@implementationXNViewController

//?將操作添加到隊列即可

-?(NSOperationQueue*)queue

{

if(!_queue)?_queue?=?[[NSOperationQueuealloc]init];

return_queue;

}

/**?=============================?暫停掛起?=============================?*/

/**?暫停操作?*/

-?(IBAction)pause

{

//?1.?判斷隊列中是否有操作

if(self.queue.operationCount==0)?{

NSLog(@"沒有操作");

return;

}

//?2.?如果沒有被掛起(正在執(zhí)行)翎朱,才需要暫停

//?只會掛起當前隊列中還沒有被調(diào)度(沒有被安排到線程上工作的操作)才會被掛起

if(!self.queue.isSuspended)?{

NSLog(@"暫停");

[self.queuesetSuspended:YES];

}else{

NSLog(@"已經(jīng)暫停");

}

}

/**?繼續(xù)操作?*/

-?(IBAction)resume

{

//?1.?判斷隊列中是否有操作

if(self.queue.operationCount==0)?{

NSLog(@"沒有操作");

return;

}

//?2.?如果有被掛起的操作橄维,才需要繼續(xù)(恢復(fù))

if(self.queue.isSuspended)?{

NSLog(@"繼續(xù)");

[self.queuesetSuspended:NO];

}else{

NSLog(@"正在執(zhí)行");

}

}

/**?========================NSOperation指定操作之間的依賴關(guān)系========================*/

-?(void)opDemo6

{

NSBlockOperation*op1=?[NSBlockOperationblockOperationWithBlock:^{

NSLog(@"正在下載蒼老師全集?。拴曲。争舞。?%@",?[NSThreadcurrentThread]);

}];

NSBlockOperation*op2=?[NSBlockOperationblockOperationWithBlock:^{

NSLog(@"正在解壓縮蒼老師全集。澈灼。竞川。?%@",?[NSThreadcurrentThread]);

}];

NSBlockOperation*op3=?[NSBlockOperationblockOperationWithBlock:^{

NSLog(@"正在保存到磁盤?。叁熔。委乌。?%@",?[NSThreadcurrentThread]);

}];

NSBlockOperation*op4=?[NSBlockOperationblockOperationWithBlock:^{

NSLog(@"下載完成?。?%@",?[NSThreadcurrentThread]);

}];

//?指定操作之間的”依賴“關(guān)系荣回,某一個操作的執(zhí)行遭贸,必須等待另一個操作完成才會開始

//?依賴關(guān)系是可以跨隊列指定的

[op2addDependency:op1];

[op3addDependency:op2];

[op4addDependency:op3];

//?***?添加依賴的時候,注意不要出現(xiàn)循環(huán)依賴

//????[op3?addDependency:op4];

[self.queueaddOperation:op1];

[self.queueaddOperation:op2];

[self.queueaddOperation:op3];

//?主隊列更新UI

[[NSOperationQueuemainQueue]addOperation:op4];

}

/**?==================================設(shè)置最大并發(fā)數(shù)====================================?*/

-?(void)opDemo5

{

//?設(shè)置隊列的最大并發(fā)數(shù)心软,隊列是負責調(diào)度操作的

/**

最大并發(fā)數(shù)的應(yīng)用場景:

1>?用戶在使用3G的時候??????????限制線程的數(shù)量壕吹,省電著蛙,省流量(省錢)

2>?用戶使用WIFI的時候(局域網(wǎng))?增加線程數(shù)量,提高用戶的體驗

maxConcurrentOperationCount?如果==?1算利,類似于串行隊列異步方法

*/

self.queue.maxConcurrentOperationCount=1;

for(inti?=0;?i?<10;?i++)?{

[self.queueaddOperationWithBlock:^{

NSLog(@"正在下載?%@?%d",?[NSThreadcurrentThread],?i);

}];

}

}

/**??=============================?Block操作册踩,添加執(zhí)行塊?=============================??*/

-?(void)opDemo4

{

//?實例化block操作

NSBlockOperation*op?=?[[NSBlockOperationalloc]init];

//?設(shè)置最大并發(fā)(操作)數(shù),不會限制執(zhí)行塊效拭!

self.queue.maxConcurrentOperationCount=2;

//?添加執(zhí)行塊

[opaddExecutionBlock:^{

NSLog(@"下載蒼老師全集1?%@",?[NSThreadcurrentThread]);

}];

//?繼續(xù)添加塊

[opaddExecutionBlock:^{

NSLog(@"下載蒼老師全集2?%@",?[NSThreadcurrentThread]);

}];

//?繼續(xù)添加塊

[opaddExecutionBlock:^{

NSLog(@"下載蒼老師全集3?%@",?[NSThreadcurrentThread]);

}];

//?繼續(xù)添加塊

[opaddExecutionBlock:^{

NSLog(@"下載蒼老師全集4?%@",?[NSThreadcurrentThread]);

}];

//?繼續(xù)添加塊

[opaddExecutionBlock:^{

NSLog(@"下載蒼老師全集5?%@",?[NSThreadcurrentThread]);

}];

//?啟動操作暂吉,在主線程執(zhí)行

//?如果執(zhí)行塊的數(shù)量超過1,就會自動進入其他線程執(zhí)行(異步)

//?具體開啟線程的數(shù)量缎患,由系統(tǒng)決定

//?執(zhí)行塊的調(diào)度與操作的調(diào)度非常像

//????[op?start];

[self.queueaddOperation:op];

}

/**?=============================?直接添加塊操作?=============================?*/

-?(void)opDemo3

{

//?只要將操作添加到隊列就會立即被調(diào)度(執(zhí)行)

for(inti?=0;?i?<10;?i++)?{

[self.queueaddOperationWithBlock:^{

NSLog(@"下載開始?%@?-?%@",?[NSThreadcurrentThread],?@(i));

}];

}

//?向主隊列中添加操作

[[NSOperationQueuemainQueue]addOperationWithBlock:^{

NSLog(@"下載開始?%@?-?%@",?[NSThreadcurrentThread],nil);

}];

}

/**=============================?NSBlockOperation?=============================*/

-?(void)opDemo2

{

for(inti?=0;?i?<10;?i++)?{

//?指定一個塊操作

NSBlockOperation*op1=?[NSBlockOperationblockOperationWithBlock:^{

NSLog(@"下載開始?%@?-?%@",?[NSThreadcurrentThread],?@(i));

}];

//?將塊操作添加到隊列.?新開線程

[self.queueaddOperation:op1];

}

}

/**?=============================NSInvocationOperation=============================?*/

-?(void)opDemo1

{

for(inti?=0;?i?<10;?i++)?{

NSInvocationOperation*op1=?[[NSInvocationOperationalloc]initWithTarget:selfselector:@selector(download:)object:@(i)];

//?如果直接啟動慕的,會在主線程執(zhí)行

//????[op1?start];

//?添加到隊列,就會新建線程挤渔,異步執(zhí)行

[self.queueaddOperation:op1];

}

}

-?(void)download:(id)obj

{

NSLog(@"下載開始?%@?-?%@",?[NSThreadcurrentThread],?obj);

}

@end

自定義NSOperation

1肮街、繼承NSOperation

2、重新main方法

[objc]view

plaincopy

@interfaceXNMyOperation?:?NSOperation

@end

//============================上為.h頭文件判导,下為.m文件=============================

@implementationXNMyOperation

//?只要重寫main就可以了

-?(void)main

{

//?自定義操作嫉父,一定要自己添加自動釋放池

@autoreleasepool{

//。眼刃。绕辖。。擂红。仪际。。昵骤。树碱。。变秦。

}

}

@end

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末成榜,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子蹦玫,更是在濱河造成了極大的恐慌伦连,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,826評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件钳垮,死亡現(xiàn)場離奇詭異惑淳,居然都是意外死亡,警方通過查閱死者的電腦和手機饺窿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評論 3 395
  • 文/潘曉璐 我一進店門歧焦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事绢馍∠虼桑” “怎么了?”我有些...
    開封第一講書人閱讀 164,234評論 0 354
  • 文/不壞的土叔 我叫張陵舰涌,是天一觀的道長猖任。 經(jīng)常有香客問我,道長瓷耙,這世上最難降的妖魔是什么朱躺? 我笑而不...
    開封第一講書人閱讀 58,562評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮搁痛,結(jié)果婚禮上长搀,老公的妹妹穿的比我還像新娘。我一直安慰自己鸡典,他們只是感情好源请,可當我...
    茶點故事閱讀 67,611評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著彻况,像睡著了一般谁尸。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上纽甘,一...
    開封第一講書人閱讀 51,482評論 1 302
  • 那天症汹,我揣著相機與錄音,去河邊找鬼贷腕。 笑死,一個胖子當著我的面吹牛咬展,可吹牛的內(nèi)容都是我干的泽裳。 我是一名探鬼主播,決...
    沈念sama閱讀 40,271評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼破婆,長吁一口氣:“原來是場噩夢啊……” “哼涮总!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起祷舀,我...
    開封第一講書人閱讀 39,166評論 0 276
  • 序言:老撾萬榮一對情侶失蹤瀑梗,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后裳扯,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體抛丽,經(jīng)...
    沈念sama閱讀 45,608評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,814評論 3 336
  • 正文 我和宋清朗相戀三年饰豺,在試婚紗的時候發(fā)現(xiàn)自己被綠了亿鲜。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,926評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡冤吨,死狀恐怖蒿柳,靈堂內(nèi)的尸體忽然破棺而出饶套,到底是詐尸還是另有隱情,我是刑警寧澤垒探,帶...
    沈念sama閱讀 35,644評論 5 346
  • 正文 年R本政府宣布妓蛮,位于F島的核電站,受9級特大地震影響圾叼,放射性物質(zhì)發(fā)生泄漏蛤克。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,249評論 3 329
  • 文/蒙蒙 一褐奥、第九天 我趴在偏房一處隱蔽的房頂上張望咖耘。 院中可真熱鬧,春花似錦撬码、人聲如沸儿倒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽夫否。三九已至,卻和暖如春叫胁,著一層夾襖步出監(jiān)牢的瞬間凰慈,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評論 1 269
  • 我被黑心中介騙來泰國打工驼鹅, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留微谓,地道東北人。 一個月前我還...
    沈念sama閱讀 48,063評論 3 370
  • 正文 我出身青樓输钩,卻偏偏與公主長得像豺型,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子买乃,可洞房花燭夜當晚...
    茶點故事閱讀 44,871評論 2 354

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