1.延時操作
GCD ? ? ? dispatch_after() ?優點:寫起來方便,直觀 ? ? ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 缺點:1. 精確度不高 ?2.沒有取消操作
例如:記住了:最好在主隊列中使用 dispatch_after 的好選擇;Xcode 提供了一個不錯的自動完成模版。
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));// 1
dispatch_after(popTime,?dispatch_get_main_queue(),?^(void){//?2
//操作任務
}
});
NSThread? performSelector:@selector(delayMethod) withObject:nil afterDelay:單線程 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 優點:精確度高 ? 可以取消延遲執行操作
2. 定時器
GCD ? ? ?優點:
NSTimer ?優點:相對精確度高 ? ? 缺點:UITableview 滾動時,timer停止
3. 信號源:線程1,線程2,線程3,他們都是異步的,正常情況是沒有順序的,加上信號員,一個結束完了,再執行另外一個,這樣就是有序了
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{? //線程一 });
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{? //線程二});
4.單例
5.隊列類型:
第一:主線程隊列
第二:全局線程隊列dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)
第三:自定義線程隊列,自定義串行隊列(當你想串行執行后臺任務并追蹤它時就是一個好選擇)dispatch_queue_t ??queue = dispatch_queue_create("cn.itcast.queue", NULL);
案例問題:當一個線程A調用讀方法 photos 的同時,另一個線程B調用寫方法 addPhoto: 在同時對一個NSMutableArray進行操作。
Dispatch barriers就是來解決這個問題的。
GCD (barrier)保證了在某個時間點上,在并行的多線程中,只有一個線程對某個資源進行訪問,其他的線程先暫停執行
怎么用這個barrier,最好只用在自定義隊列中的并發隊列,原因:barrier肯定是用在異步線程中,首先主線程用不上,然后就是全局并發隊列,要小心;這可能不是最好的主意,因為其它系統可能在使用隊列而且你不能壟斷它們只為你自己的目的。最后. 自定義串行隊列
打開 PhotoManager.m,添加如下私有屬性到類擴展中:
@interfacePhotoManager?()
@property?(nonatomic,strong,readonly)?NSMutableArray?*photosArray;
@property?(nonatomic,?strong)?dispatch_queue_t?concurrentPhotoQueue;///<?Add?this
@end
找到 addPhoto: 并用下面的實現替換它:
-?(void)addPhoto:(Photo?*)photo{
if(photo)?{//?1
dispatch_barrier_async(self.concurrentPhotoQueue,?^{//?2
[_photosArray?addObject:photo];//?3
dispatch_async(dispatch_get_main_queue(),?^{//?4
[self?postContentAddedNotification];});});}
}
這個并沒有結束哦,這就處理了寫操作,但你還需要實現 photos 讀方法并實例化 concurrentPhotoQueue 。在寫者打擾的情況下,要確保線程安全,你需要在 concurrentPhotoQueue 隊列上執行讀操作。既然你需要從函數返回,你就不能異步調度到隊列,因為那樣在讀者函數返回之前不一定運行。
在這種情況下,dispatch_sync 就是一個絕好的候選。
- (NSArray *)photos
{__block?NSArray?*array;//?1
dispatch_sync(self.concurrentPhotoQueue,?^{//?2
array?=?[NSArray?arrayWithArray:_photosArray];//?3
});returnarray;}
最后,你需要實例化你的 concurrentPhotoQueue 屬性。修改 sharedManager 以便像下面這樣初始化隊列:
+?(instancetype)sharedManager
{
staticPhotoManager?*sharedPhotoManager?=?nil;
staticdispatch_once_t?onceToken;
dispatch_once(&onceToken,?^{
sharedPhotoManager?=?[[PhotoManager?alloc]?init];
sharedPhotoManager->_photosArray?=?[NSMutableArray?array];
//?ADD?THIS:
sharedPhotoManager->_concurrentPhotoQueue?=?dispatch_queue_create("com.selander.GooglyPuff.photoQueue",DISPATCH_QUEUE_CONCURRENT);
});
returnsharedPhotoManager;
}
? ?