GCD 总结(一)
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;
}