在之前的一些系列博客中,对iOS中线程的管理作了总结,其中涵盖了GCD的相关基础知识:http://my.oschina.net/u/2340880/blog/417746。那里面将GCD的线程管理能力,列队组能力,经过信号和消息控制程序流程的能力都有介绍,这里,咱们继续深刻GCD的功能,经过GCD来处理一些逻辑更加复杂的代码功能。编程
当咱们在程序中处理延时任务的时候,咱们通常会经过两种方式,一种是经过定时器进行延时执行,另一种是经过以下的函数:安全
- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay;
然而,若是咱们须要在多线程中进行延时操做,上面两种方式会显得十分麻烦,而且徒增代码的复杂度。GCD为咱们提供了一种方式:多线程
void dispatch_after(dispatch_time_t when, dispatch_queue_t queue, dispatch_block_t block);异步
这个方法有三个参数,第一个参数延时的时间,第二个参数为将任务加入的队列,第三个block为要执行的任务。示例以下:async
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ NSLog(@"1233"); });
这里经过dispatch_time来建立时间对象,将打印信息的方法在3S后加入主线程队列。须要注意的是,这里只是将任务延时加入队列,并非执行,若是是加入同步队列中,则会进入等待状态。函数
在进行多线程编程时,或许总会遇到一类问题,数据的竞争与线程的安全。这些问题若是咱们经过程序手动来控制难度将会很是大。GCD一样为咱们简单的解决了这样的问题。spa
首先,若是只是在读取数据,而不对数据作任何修改时,咱们并不须要处理安全问题,可让多个任务同时进行读取,但是若是要对数据进行写的操做,那么在同一时间,咱们就必须只能有一个任务在写,GCD中有一个方法帮咱们完美的解决了这个问题,代码以下:.net
//建立一个队列 dispatch_queue_t queue = dispatch_queue_create("oneQueue", DISPATCH_QUEUE_CONCURRENT); //几个任务同时读操做 dispatch_async(queue, ^{ for (int i=0; i<5; i++) { NSLog(@"read1:%d",i); } }); dispatch_async(queue, ^{ for (int i=0; i<5; i++) { NSLog(@"read2:%d",i); } }); //此处进行写操做 /* 下面这个函数在加入队列时不会执行,会等待已经开始的异步执行所有完成后再执行,而且在执行时,会阻塞其余任务 执行完成后,其余任务从新进入异步执行 */ dispatch_barrier_async(queue, ^{ for (int i=0; i<5; i++) { NSLog(@"write:%d",i); } }); //继续进行异步读操做 dispatch_async(queue, ^{ for (int i=0; i<5; i++) { NSLog(@"read3:%d",i); } }); dispatch_async(queue, ^{ for (int i=0; i<5; i++) { NSLog(@"read4:%d",i); } }); dispatch_async(queue, ^{ for (int i=0; i<5; i++) { NSLog(@"read5:%d",i); } });
打印信息以下:线程
能够看出,读操做是异步进行的,写操做是等待后阻塞任务队列独立进行,结束后队列恢复异步执行读操做,这正是咱们须要的效果。code
一般状况下,咱们的单例会是以下的样子:
+(instancetype)shared{ static Auto * obj; if (obj==nil) { obj = [[Auto alloc]init]; } return obj; }
这种经过读取静态变量的方式在大多数状况下是没问题的,但是并不能保证程序百分百的安全,由于在多线程的操做中,会有可能初始化多个对象,在GCD中,咱们可使用以下方式:
+(instancetype)shared{ static Auto * obj; //dispatch_once_t对象能够只保证执行一次 static dispatch_once_t once; dispatch_once(&once, ^{ obj = [[Auto alloc]init]; }); return obj; }
专一技术,热爱生活,交流技术,也作朋友。
——珲少 QQ群:203317592