//// 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