1 、最常用的一个: 耗时操作放到子线操作,刷新UI等操作返回主线程中
dispatch_async(dispatch_get_global_queue(0,0), ^{
NSURL * url = [NSURLURLWithString:@"https://www.baidu.com/img/bdlogo.png"];
NSData * data = [NSDatadataWithContentsOfURL:url];
NSLog(@"下载完成");
//_imageView.image = [UIImage imageWithData:data];//这一步应在主线程操作 (面试:所有 UI操作必须在主线程里进行)
dispatch_async(dispatch_get_main_queue(), ^{
_imageView.image = [UIImageimageWithData:data];
});
});
2、创建异步串行队列
//创建一个串行队列
dispatch_queue_t queue =dispatch_queue_create("queue1_name",DISPATCH_QUEUE_SERIAL);
//将任务放入串行队列中
dispatch_async(queue, ^{
for (int i =0 ; i <1000; i++) {
NSLog(@"操作1");
}
});
dispatch_async(queue, ^{
for (int i =0 ; i <1000; i++) {
NSLog(@"操作2");
}
dispatch_async(dispatch_get_main_queue() , ^{
NSLog(@"放回到主线程执行某操作");
});
});
3、创建同步并行队列
dispatch_queue_t queue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
NSArray *array =@[@1,@2,@3,@4,@5,@6];
//同步执行
dispatch_apply(array.count, queue, ^(size_t index) {
NSLog(@"%@",array[index]);
});
4、创建异步并行队列
dispatch_queue_t queue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
NSArray *array =@[@1,@2,@3,@4,@5,@6];
dispatch_async(queue, ^{
dispatch_apply(array.count, queue, ^(size_t index) {
NSLog(@"%@",array[index]);
});
});
5、dispatch_group_t
//异步操作,操作完成有dispatch_group_notify的回调
//可以实现监听一组任务是否完成,完成后得到通知执行其他的操作.比如下载操作
dispatch_queue_t queue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
dispatch_group_t group =dispatch_group_create();
dispatch_group_async(group, queue, ^{
NSLog(@"操作1");
});
dispatch_group_async(group, queue, ^{
NSLog(@"操作2");
});
dispatch_group_async(group, queue, ^{
NSLog(@"操作3");
});
dispatch_group_async(group, queue, ^{
NSLog(@"操作4");
});
// 监听所有任务完成
dispatch_group_notify(group,dispatch_get_main_queue(), ^{
NSLog(@"结束");
});
//该函数是个阻塞式的等待,当我们将第二个参数设置为DISPATCH_TIME_FOREVER时,群组任务不执行完,后续代码就会无法执行,也就是说只要任务不执行完,`~~~~`就不会打印。
//dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
//NSLog(@"~~~~~");
5、 dispatch_barrier_async
//dispatch_barrier_async是在前面的任务执行结束后它才执行,而且它后面的任务等它执行完成之后才会执行
dispatch_queue_t queue =dispatch_queue_create("s_name",DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSLog(@"dispatch_async2");
});
dispatch_async(queue, ^{
NSLog(@"dispatch_async1");
});
dispatch_async(queue, ^{
NSLog(@"dispatch_async3");
});
dispatch_barrier_async(queue, ^{
NSLog(@"dispatch_barrier_async");
});
//下面的操作要等到 dispatch_barrier_async 执行完才会执行
dispatch_async(queue, ^{
NSLog(@"dispatch_async4");
});
6、GCD 计时器
内部实现的原理和NSTimer是一样的。网上找的一个栗子:
__blockint time =30;
CGFloat reSecond =1.0;
dispatch_queue_t queue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
dispatch_source_t timer =dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER,0,0, queue);
dispatch_source_set_timer(timer,DISPATCH_TIME_NOW, reSecond *NSEC_PER_SEC,0);
dispatch_source_set_event_handler(timer, ^{
time--;
NSLog(@"%d", time);
if (time ==0) {
dispatch_source_cancel(timer);
}
});
dispatch_resume(timer);
7、单例模式更好的解决方案dispatch_once
+ (instancetype)shareManager{
staticNXViewController *share =nil ;
staticdispatch_once_t predicate ;
dispatch_once(&predicate, ^{
share = [[selfalloc]init];
});
return share ;
}
其他操作
dispatch_queue_t queue = dispatch_queue_create("Load Image", NULL);
//执行一个队列
dispatch_async(queue, ^{//异步执行
});
dispatch_sync(queue, ^{ //同步执行
});
//暂停一个队列
dispatch_suspend(queue);
//恢复一个队列
dispatch_resume(queue);
//判断是否是在子线程
BOOL isMulti = [NSThreadisMultiThreaded];
注意事项:
1 、UIKit的方法都必须放在主线程中调用,事实上很多不涉及UI操作的UIKit方法都不能在子线程中调用。
如果执行的任务需要访问一些共享的资源,那么在不同优先级的队列中调度这些任务很快就会造成不可预期的行为。这样可能会引起程序的完全挂起,因为低优先级的任务阻塞了高优先级任务,使它不能被执行。
2 、队列的优先级尽量使用 DISPATCH_QUEUE_PRIORITY_DEFAULT
3 、 注意dispath_sync 可能会引起死锁情况。应尽量避免使用它。
代码示例:https://github.com/chuangchen/GCD_learning
参考资料
http://www.dreamingwish.com/article/gcd-practice-simple-preload.html
http://blog.csdn.net/totogo2010/article/details/8016129