//// GCD_ViewController.m// ZM_NSThreadGCD//// Created by ZM on 2015/2/9.// Copyright © 2015年ZM. All rights reserved.//#import"GCD_ViewController.h"#import "BaseHeader.h"@interfaceGCD_ViewController ()@end@implementationGCD_ViewController- (void)viewDidLoad { [superviewDidLoad]; self.title= @"GCD_VC"; NSString *title=@""; CGFloat width = 120; for (inti=1; i<11; i++) { title = [NSStringstringWithFormat:@"case%d",i]; [selfaddBtnTitle:titleframe:CGRectMake(10,50+ (35+10)*i, width, 35)Tag:i]; } CGFloat yy = SSHEIGHT-90; [selfaddBtnTitle:@"attentionCase3_1"frame:CGRectMake(10, yy, width, 35)Tag:111]; [selfaddBtnTitle:@"attentionCase3_2"frame:CGRectMake(10*2+width, yy, width, 35)Tag:222]; [selfaddBtnTitle:@"solveCase3_1"frame:CGRectMake(10, yy+45, width,35)Tag:333]; }- (void)myBtnClick:(UIButton*)Btn{ if (Btn.tag==1) { [selfcase1]; }elseif (Btn.tag==2) { [selfcase2]; }elseif (Btn.tag==3) { [selfcase3]; }elseif (Btn.tag==4) { [selfcase4]; }elseif (Btn.tag==5) { [selfcase5]; }elseif (Btn.tag==6) { [selfcase6]; }elseif (Btn.tag==7) { [selfcase7]; }elseif (Btn.tag==8) { [selfcase8]; }elseif (Btn.tag==9) { [selfcase9]; } if (Btn.tag==111) { [selfattentionCase3_1]; }elseif (Btn.tag==222) { [selfattentionCase3_2]; }elseif (Btn.tag==333) { [selfsolveCase3_1]; }}/** * 以下4个GCD方法的区别: dispatch_async 异步任务 dispatch_sync 同步任务 dispatch_barrier_async 为异步执行调度队列:提交一个路障 dispatch_barrier_sync 为同步执行调度队列:提交一个路障 dispatch_get_main_queue 主队列 dispatch_queue_t 并行队列 dispatch_get_global_queue 全局并行队列 *///例一:dispatch_sync同步任务 提交Block在主线程 中执行- (void)case1 { dispatch_queue_t queue1 = dispatch_queue_create("并行",DISPATCH_QUEUE_CONCURRENT); dispatch_sync(queue1, ^{ NSLog(@"%@",[NSThreadcurrentThread]); //输出结果:{number = 1, name = main} });}//例二:dispatch_async异步任务 提交Block在分线程 中执行- (void)case2 { dispatch_queue_t queue1 = dispatch_queue_create("并行",DISPATCH_QUEUE_CONCURRENT); dispatch_async(queue1, ^{ NSLog(@"%@",[NSThreadcurrentThread]); //输出结果:{number = 3, name = (null)} });}//例三:我们分别用sync和async向主队列提交Block,结果Block都是在主线程中执行:- (void)case3 { //我们用sync如下的方式去提交Block: dispatch_queue_t queue1 = dispatch_queue_create("并行",DISPATCH_QUEUE_CONCURRENT); dispatch_async(queue1, ^{ dispatch_sync(dispatch_get_main_queue(), ^{ NSLog(@"%@",[NSThreadcurrentThread]); //输出结果:{number = 1, name = main} }); }); }//注意3_1:在主线程不能用sync(同步)提交Block执行任务,否则会引起死锁:- (void)attentionCase3_1 { dispatch_sync(dispatch_get_main_queue(), ^{ NSLog(@"任务一"); }); NSLog(@"任务二"); //因为往queue中提交Block,总是追加在队列尾部的,而queue执行Block的顺序为先进先出(FIFO),所以任务一需要在当前队列它之前的任务(任务二)全部执行完,才能轮到它。 //任务一等待任务二完成,任务二等待任务一完成,相互等待_被阻塞,程序被死锁在这了}//注意3_2:在主线程能用async(异步)提交Block执行任务- (void)attentionCase3_2 { dispatch_async(dispatch_get_main_queue(), ^{ NSLog(@"%@",[NSThreadcurrentThread]); //输出结果:{number = 1, name = main} });}//解决3_1 问题- (void)solveCase3_1 { // 全局并行队列 // 这应该是唯一一个并行队列, 只要是并行任务一般都加入到这个队列。这是系统提供的一个并发队列。 // 因为全局队列和主队列是两个队列,所以任务一的执行,并不需要等待任务二。 dispatch_sync(dispatch_get_global_queue(0,0), ^{ NSLog(@"任务一"); }); NSLog(@"任务二");}//例四:建立栅栏_执行任务dispatch_barrier_async- (void)case4 { dispatch_queue_t queue = dispatch_queue_create("queue",DISPATCH_QUEUE_CONCURRENT); dispatch_async(queue, ^{ NSLog(@"任务1"); }); dispatch_async(queue, ^{ NSLog(@"任务2"); }); dispatch_async(queue, ^{ NSLog(@"任务3"); }); //建立栅栏_执行任务dispatch_barrier_async dispatch_barrier_async(queue, ^{ NSLogline(@"/n %@/n %@/n %@", @"任务1,2,3的顺序不一定", @"任务4_在中间", @"最后是5、6、7、8、9任务顺序不一定"); }); dispatch_async(queue, ^{ NSLog(@"任务5"); }); dispatch_async(queue, ^{ NSLog(@"任务6"); }); dispatch_async(queue, ^{ NSLog(@"任务7"); }); dispatch_async(queue, ^{ NSLog(@"任务8"); }); dispatch_async(queue, ^{ NSLog(@"任务9"); }); //结论:dispatch_barrier_async 它的作用可以用一个词概括--承上启下,它保证此前的任务都先于自己执行,此后的任务也迟于自己执行。当然它的作用导致它只有在并行队列中有意义。 //注意:当然这里有一点需要注意的是:dispatch_barrier_(a)sync只在自己创建的并发队列上有效,在全局(Global)并发队列、串行队列上,效果跟dispatch_(a)sync效果一样。 //3)dispatch_barrier_sync这个方法和dispatch_barrier_async作用几乎一样,都可以在并行queue中当做栅栏。 //唯一的区别就是:dispatch_barrier_sync有GCD的sync共有特性,会阻塞提交Block的当前线程,而dispatch_barrier_async是异步提交,不会阻塞。}//例五:例如我们在一个读写操作中,我们就可以如下使用:- (void)case5 { //一个读写操作中:我们要知道一个数据,读与读之间是可以用线程并行的,但是写与写、写与读之间,就必须串行同步或者使用线程锁来保证线程安全。但是我们有了dispatch_barrier_async dispatch_queue_t queue = dispatch_queue_create("queue",DISPATCH_QUEUE_CONCURRENT); dispatch_async(queue, ^{ NSLog(@"读操作_1"); }); dispatch_async(queue, ^{ NSLog(@"读操作_2"); }); dispatch_barrier_async(queue, ^{ NSLog(@"写操作_1"); }); dispatch_barrier_async(queue, ^{ NSLog(@"写操作_2"); }); dispatch_async(queue, ^{ NSLog(@"读操作"); }); //结论:这样写操作的时候,始终只有它这一条线程在进行。而读操作一直是并行的。这么做充分利用了多线程的优势,还不需要加锁,减少了相当一部分的性能开销。实现了读写操作的线程安全。 //读与读:线程并行 //写与写、写与读:必须串行同步或者使用线程锁}//例六:4)dispatch_sync,我们来讲讲它和dispatch_barrier_sync的区别。二者因为是sync提交,所以都是阻塞当前提交Block线程。 //而它俩唯一的区别是:dispatch_sync并不能阻塞并行队列。其实之前死锁有提及过,担心大家感觉疑惑,还是写个例子:- (void)case6 { dispatch_queue_t queue = dispatch_queue_create("并行",DISPATCH_QUEUE_CONCURRENT); // dispatch_sync dispatch_sync(queue, ^{ dispatch_async(queue, ^{ NSLog(@"任务二"); }); dispatch_async(queue, ^{ NSLog(@"任务三"); }); //睡眠2秒// [NSThread sleepForTimeInterval:2]; NSLog(@"任务一/n "); }); //输出结果:任务三 任务二 任务一 (二、三顺序不固定,一最后,很显然,并行队列没有被sync所阻塞。)}//例七:而dispatch_barrier_sync 可以阻塞并行队列(栅栏作用的体现):- (void)case7 { dispatch_queue_t queue = dispatch_queue_create("并行",DISPATCH_QUEUE_CONCURRENT); // dispatch_barrier_sync dispatch_barrier_sync(queue, ^{ dispatch_async(queue, ^{ NSLog(@"任务二"); }); dispatch_async(queue, ^{ NSLog(@"任务三"); }); //睡眠2秒// [NSThread sleepForTimeInterval:2]; NSLog(@"任务一"); }); //输出结果:任务一 任务二 任务三 (一首先,二、三顺序不固定)}/** 同:dispatch_sync、dispatch_barrier_sync 都能阻塞 主队列 区别:dispatch_sync不能阻塞并行队列 dispatch_barrier_sync 可以阻塞并行队列 */- (void)case8 { }- (void)case9 { }@end