Chapter 6. Blocks and Grand Central Dispatch
<br />
(昨天問(wèn)大神死鎖的問(wèn)題的時(shí)候,大神推薦去看《Objective-C高級(jí)編程》這本,看了一下GCD部分覺(jué)得寫得比這本清楚誒,后悔沒(méi)早看!如果先看那本再看這本的第六章會(huì)比較好一點(diǎn)。)
Item 43: Know When to Use GCD and When to Use Operation
<br />
這一節(jié)講GCD和NSOperationQueue用法上的區(qū)別,主要是NSOperationQueue比GCD更方便的地方。不過(guò)沒(méi)有給代碼例子。等我過(guò)幾天補(bǔ)上。
GCD是調(diào)用c語(yǔ)言函數(shù),NSOperation是OC對(duì)象,底層是用GCD來(lái)實(shí)現(xiàn)的,所以更重量級(jí)一些。雖然一般認(rèn)為調(diào)用越底層的東西效率越高,作者的意見(jiàn)是也不能盲目迷信底層,還是要具體問(wèn)題具體分析。
把文中內(nèi)容和Reference合一下:
- Operation Dependency: 涉及兩個(gè)方法
addDependency:和removeDependency:,當(dāng)一個(gè)operation依賴的最后一個(gè)operation完成的時(shí)候,這個(gè)operation才會(huì)被執(zhí)行。這里的“完成”包括成功和不成功的情況。 - KVO-Compliant Properties: NSOperation特別適合KVO監(jiān)聽,提供的監(jiān)聽屬性很多,比如isCancelled, isAsynchronous, isExecuting, isFinished等等,這使得可以針對(duì)不同狀態(tài)寫不同的代碼,處理就比GCD細(xì)致很多。
- Multicore Considerations: NSOperation支持多核。在多個(gè)線程調(diào)用它的方法可以保證thread-safe。所以自定義NSOperation子類的時(shí)候,也要保證重寫或者添加的方法要thread-safe。
- Cancelling: 直接調(diào)用cancel方法就可以,但必須在任務(wù)運(yùn)行之前,如果已經(jīng)啟動(dòng)就不能取消了。
Priority: NSOperation有單獨(dú)針對(duì)某個(gè)操作的優(yōu)先級(jí),也有線程優(yōu)先級(jí),而GCD只有隊(duì)列優(yōu)先級(jí),所以NSOperation的劃分更加細(xì)致了。 - Reuse of Operations:NSOperation本身是一個(gè)抽象類,有兩個(gè)系統(tǒng)給的子類,NSInvocationOperation和NSBlockOperation,當(dāng)然也可以自定義。
最后文中舉了一個(gè)使用NSOperation做API的例子,NSNotificationCenter:
- (id)addObserverForName:(NSString *)name object:(id)object queue:(NEOperationQueue *)queue usingBlock:(void(^)(NSNotification *))block
<br />
Item 44: Use Dispatch Groups to Take Advantage of Platform Scaling
<br />
這一節(jié)講dispatch group的用法。
Dispatch group主要用在需要等多個(gè)任務(wù)完成后再進(jìn)行一個(gè)結(jié)束處理的情況(其實(shí)我有點(diǎn)糾結(jié)它和dispatch barrier的區(qū)別…如果把多個(gè)任務(wù)放到concurrent dispatch queue,然后把結(jié)束處理放到barrier里,感覺(jué)效果是差不多的?但是《Objective-C高級(jí)編程》這本里面說(shuō)“雖然用dispatch group和dispatch_set_target_queue也可實(shí)現(xiàn),但是源代碼會(huì)很復(fù)雜”,我不是很懂),多個(gè)任務(wù)一般是采用并發(fā)隊(duì)列,如果是串行隊(duì)列好像就沒(méi)什么意義?;镜挠梅ú毁樖隽?,這里我筆記兩個(gè)細(xì)節(jié):
多個(gè)任務(wù)不是一定要放到一個(gè)并發(fā)隊(duì)列的,可以放到多個(gè),而且可以分不同優(yōu)先級(jí)。
dispatch_apply,按指定次數(shù)將相應(yīng)的block追加到指定的dispatch queue中,并等待全部處理執(zhí)行結(jié)束。用法:
void dispatch_apply(size_t iterations, dispatch_queue_t queue, void(^block)(size_t));
第一個(gè)參數(shù)重復(fù)次數(shù),第二個(gè)是追加到的queue,第三個(gè)就是追加的block。需要注意的是dispatch_apply和dispatch_sync一樣會(huì)等待處理執(zhí)行結(jié)束,容易引起死鎖,所以推薦在dispatch_async函數(shù)中非同步地執(zhí)行dispatch_apply函數(shù)。像這樣:
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
dispatch_apply(…);
});
<br />
Item 45: Use dispatch_once for Thread-Safe Single-Time Code Execution
<br />
這一節(jié)講dispatch_once。這一節(jié)好短??!不過(guò)我喜歡,2333333
void dispatch_once(dispatch_once_t *token, dispatch_block_t block);
這是一個(gè)保證在應(yīng)用程序執(zhí)行中block只執(zhí)行一次的函數(shù),完全的thread-safe,而且還很高效。第一個(gè)參數(shù)token一般聲明為靜態(tài),來(lái)保證每次調(diào)用函數(shù)時(shí)看到的token是一致的。以實(shí)現(xiàn)單例的sharedInstance方法為例:
+ (id)sharedInstance {
static EOCClass *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}