今天主要讲下dispatch_barrier_async、dispatch_after、dispatch_once
1、dispatch_barrier_async 顾名思义,barrier有栅栏、阻碍、分界线的意思。dispatch_barrier_async函数允许你在一个并发队列上创建一个同步点。当并发队列在执行过程中遇到这个barrier,并发队列会延迟执行,不会继续往下执行,直到barrier之前的并发操作全部完成。使用该函数需要注意,队列必须是自己创建的并发队列,不能是串行队列或全局的并发队列,否则效果和dispatch_async一样。示例代码如下:
dispatch_queue_t concurrentQueue = dispatch_queue_create("concurrent", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(concurrentQueue, ^{
NSLog(@" task1 begin");
[NSThread sleepForTimeInterval:2];
NSLog(@" task1 end");
});
dispatch_async(concurrentQueue, ^{
NSLog(@" task2 begin");
[NSThread sleepForTimeInterval:5];
NSLog(@" task2 end");
});
//加上栅栏,堵住了并发队列的异步操作。下面的操作不会执行,直到栅栏以上的代码执行完成。不加栅栏,task3会立即执行
dispatch_barrier_async(concurrentQueue, ^{
NSLog(@"在这里插入了一段代码,等待上面的任务执行结束再执行,包括下面的task3");
});
dispatch_async(concurrentQueue, ^{
NSLog(@" task3 begin");
NSLog(@" task3 end");
});
2、dispatch_after 这个是用的最频繁的一个GCD函数了,可以在指定时间后向指定队列插入任务。注意:这不是在指定时间后再执行,而是把任务指定时间插到指定队列执行.奇怪的是,如果把dispatch_after要执行的任务加到并发队列中的话,会新产生一个线程,和并发队列的线程不是同一个线程,并且dispatch_after插入的任务会在放进队列后立即执行(因为是新起了一个线程)。如果是串行队列的话,则是原来的意思:在指定时间后向指定队列插入任务。如果此时队列中没有资源的话,dispatch_after的任务就不会立即执行。示例代码:
//注意这里的队列类型
dispatch_queue_t concurrentQueue = dispatch_queue_create("concurrent", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(concurrentQueue, ^{
NSLog(@"begin in %@",NSThread.currentThread);
[NSThread sleepForTimeInterval:5];
NSLog(@"end in %@",NSThread.currentThread);
});
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2*NSEC_PER_SEC)), concurrentQueue, ^{
NSLog(@"i am a hero in %@",NSThread.currentThread);
});
3、dispatch_once 该函数是保证在APP生命周期内,执行的任务只会被执行一次,并且是线程安全的,通常用来创建单例对象(比synchronized方法要有更高的性能)。示例代码如下:
+(instancetype)sharedInstance{
static MyClass *instance =nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[MyClass alloc]init];
});
return instance;
}