GCD(用法一)
GCD线程通讯:
在iOS开发过程中,我们一般在主线程里边进行UI刷新。我们通常会把一些耗时的操作放在其他线程,比如说图片下载、文件上传等。而当我们有时候在其他线程完成了耗时操作时,需要回到主线程,那么就用到了线程之间的通讯。已下载图片为例:
- (void)communication {
__weak typeof(self) weakSelf = self;
self.imageView.image= [UIImageimageNamed:@"屏幕快照"];
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_async(globalQueue, ^{
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://img95.699pic.com/desgin_photo/40084/3149_detail.jpg"]]];
dispatch_async(mainQueue, ^{
weakSelf.imageView.image= image;
});
});
}
GCD单例:dispatch_once
void dispatch_once( dispatch_once_t *predicate, dispatch_block_t block);
//第一个参数predicate,该参数是检查后面第二个参数所代表的代码块是否被调用的谓词。
//第二个参数则是在整个应用程序中只会被调用一次的代码块。dispach_once函数中的代码块只会被执行一次,而且还是线程安全的。
我们在创建单例、或者有整个程序运行过程中只执行一次的代码时,我们就用到了 dispatch_once 函数。它能保证某段代码在程序运行过程中只被执行一次,并且即使在多线程的环境下,它也可以保证线程安全。单例为例:
+ (instancetype)sharedInstance {
static GCDTimer *manager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
manager = [[GCDTimer alloc] init];
});
returnmanager;
}
GCD 延时执行:dispatch_after
当我们需要延迟执行一段代码时,就需要用到dispatch_after方法,dispatch_after是延迟将任务提交到队列中,不要理解成延迟执行任务。
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3*NSEC_PER_SEC));
dispatch_after(time, dispatch_get_main_queue(), ^{
NSLog(@"after");
});
GCD 快速迭代:dispatch_apply
dispatch_apply按照指定的次数将指定的任务追加到指定的队列中,并等待全部队列执行结束。可以快速完成对顺序没有要求的集合进行遍历。如果是在串行队列中使用此函数,那么就和 for 循环一样,按顺序同步执行。可这样就体现不出快速迭代的意义了。我们可以利用并发队列进行异步执行。比如说遍历 0~5 这6个数字,for 循环的做法是每次取出一个元素,逐个遍历。此函数可以在多个线程中同时(异步)遍历多个数字。提升速度,所以建议在异步执行中使用此函数。
- (void)apply {
NSLog(@"begin");
NSLog(@"%@",[NSThread currentThread]);
dispatch_apply(5, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t i) {
NSLog(@"%@我开始执行 %zu times",[NSThreadcurrentThread],i+1);
});
NSLog(@"end");
}
GCD 栅栏:dispatch_barrier
一个dispatch_barrier允许在一个并发队列中创建一个同步点。当在并发队列中遇到一个barrier,他会延迟执行barrier的任务,等待所有在barrier之前提交的任务执行结束。 这时barrier的任务自己开始执行。 之后队列继续正常的执行操作。
- (void)barrier
{
NSLog(@"begin");
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSLog(@"----1-----%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"----2-----%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"----3-----%@", [NSThread currentThread]);
});
dispatch_barrier_async(queue, ^{
NSLog(@"----barrier-----%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"----4-----%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"----5-----%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"----6-----%@", [NSThread currentThread]);
});
NSLog(@"end");
}
注意:这里指定的并发队列应该是自己通过dispatch_queue_create函数创建的。如果你传的是一个串行队列或者全局并发队列,这个函数等同于dispatch_async函数。
区别:dispatch_barrier_sync和dispatch_barrier_async
1、dispatch_barrier_sync将自己的任务插入到队列的时候,需要等待自己的任务结束之后才会继续插入被写在它后面的任务,然后执行它们。
2、dispatch_barrier_async将自己的任务插入到队列之后,不会等待自己的任务结束,它会继续把后面的任务插入到队列,然后等待自己的任务结束后才执行后面任务。