Grand Central Dispatch(GCD)包含語言特點、運行庫和系統增強功能,它提供系統的、綜合的改進,進而去支持并發代碼在iOS和OSX多核硬件上的執行。
子系統、CoreFoundation和Cocoa APIs 已經都延伸去使用這些功能,進而幫助系統和你的應用程序運行地更快,更高效,而且提高響應能力。考慮到一個程序有效使用多核的困難性,更不要說在不同的計算機中使用不同數量的計算機內核或者多個應用程序環境中競爭核。CGC,一個在系統層面的操作,可以更好的適應所有運行程序的需要,以平衡的方式去匹配可用系統資源。
這個文檔用來描述GCD 的API,它在Unix系統水平支持異步執行操作。你可以使用這些API來管理與文件描述符、Mach 端口、信號或者計時器的相互作用。在OS Xv10.7以及以后,你也可以使用GCD去處理常規目的的異步I/O操作。
GCD并不限制于系統級別的應用程序,但是在你使用它到更高級別的應用程序中之前,你應該考慮一下Cocoa提供的簡單的函數是不是比GCD更簡單去滿足你程序的需求。
當你在把CGD和fork系統調用混合適用的時候,如果一個進程GCD調用優先于fork調用,這樣就是不安全的。指導成功調用exec或者相關函數之后才安全。
void dispatch_async ( dispatch_queue_t queue, dispatch_block_t block );void dispatch_sync ( dispatch_queue_t queue, dispatch_block_t block );串行隊列:任務一個接著一個執行。
dispatch_get_global_queue函數獲得全局的并發隊列。創建串行隊列
串行隊列可以通過以下兩種方式獲得:
dispatch_queue_create創建dispatch_get_main_queue(),朱隊列是GCD自帶的一種特殊的串行隊列,放在主隊列的任務都會在主線程中執行。當你使用OC編譯器運行你的app時,所有的dispatch對象都是OC對象。同樣的,當自動引用計數(ARC)允許時,dispatch對象的保持和釋放都是自動的,就像其他OC對象一樣。當ARC不允許時,使用dispatch_retain和dispatch_release函數(或者OC語言)去保持和釋放你的dispatch對象。你不能使用Core Foundation retain/release函數去保持和釋放dispatch對象。
在晚一些的的項目構建中,如果你需要在ARC允許的app中使用retain/release語法(為了維護與現有代碼的兼容性),你可以禁用OC dispathc對象通過添加 -DOS_OBJECT_USE_OBJE=0到你的編譯器標示中。
dispatch_ get_main_queuedispatch_queue_t dispatch_get_main_queue ( void );主線程上調用異步
- (void)syncOnMainThread{ NSLog(@"task2:%@",[NSThread currentThread]); dispatch_queue_t queue = dispatch_get_main_queue(); dispatch_async(queue, ^{ NSLog(@"task1:%@",[NSThread currentThread]); }); NSLog(@"task3:%@",[NSThread currentThread]);}輸出結果:
死鎖:使用同步函數在主隊列執行,會造成線程死鎖情況
- (void)testDeadLock{ NSLog(@"task2:%@",[NSThread currentThread]); dispatch_queue_t queue = dispatch_get_main_queue(); dispatch_sync(queue, ^{ NSLog(@"task1:%@",[NSThread currentThread]); }); NSLog(@"task3:%@",[NSThread currentThread]);}同步執行串行隊列:不會開啟新線程,按照順序執行
- (void)syncChuanxing{ dispatch_queue_t queue = dispatch_queue_create("gcd.queue", NULL); //添加任務到隊列中執行任務 dispatch_sync(queue, ^{ NSLog(@"task1:%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"task2:%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"task3:%@",[NSThread currentThread]); });}執行結果:
在同步函數中執行并發任務:在主線程中按順序執行,并發隊列失去并發功能
- (void)syncBingfa{ dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); //添加任務到隊列中執行任務 dispatch_sync(queue, ^{ NSLog(@"task1:%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"task2:%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"task3:%@",[NSThread currentThread]); }); }執行結果:
異步函數在串行隊列上執行:可見程序開啟單個線程的順序執行
- (void)asynChuanxing{ //獲得全局的并發隊列 dispatch_queue_t queue =dispatch_queue_create("gcd.queue", NULL);// dispatch_queue_t queue =dispatch_get_main_queue(); //添加任務到隊列中執行任務 dispatch_async(queue, ^{ NSLog(@"task1:%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"task2:%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"task3:%@",[NSThread currentThread]); });}執行結果:
異步函數在并行隊列上執行
- (void)asynBingxing{ //獲得全局的并發隊列 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); //添加任務到隊列中執行任務 dispatch_async(queue, ^{ NSLog(@"task1:%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"task2:%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"task3:%@",[NSThread currentThread]); });}執行結果:
每次執行的結果可能不一樣
延時執行
- (void)deleayRun{ //通常的延時執行 dispatch_queue_t queue = dispatch_get_main_queue(); dispatch_async(queue, ^{ [self performSelector:@selector(runWith:) withObject:@"2" afterDelay:2.0]; }); //gcd函數執行 dispatch_queue_t queue1 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0*NSEC_PER_SEC)); dispatch_after(when, queue1, ^{ [self runWith:1]; }); //上邊的gcd函數執行和這個一樣 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self runWith:2]; }); }#pragma mark - RunMethod- (void)runWith:(NSInteger)tag{ NSLog(@"執行函數:%ld",(long)tag);}組隊列
- (void)zuDuiLie{ // 創建一個組 dispatch_group_t group = dispatch_group_create(); // 下載圖片1 dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSLog(@"下載圖片1:%@",[NSThread currentThread]); }); // 下載圖片2 dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSLog(@"下載圖片2:%@",[NSThread currentThread]); }); // group任務都執行完畢,再執行其他操作 dispatch_group_notify(group, dispatch_get_main_queue(), ^{ // 合并圖片 NSLog(@"開始合并圖片:%@",[NSThread currentThread]); });}執行結果:
1、 線程:1個CPU執行的CPU命令列為一條無分叉的路徑即為一個線程。
2、dispatch_queue_create的作用是創建一個派遣隊列,是串行隊列。
3、dispatch_set_target_queue:變更生成的Dispatch_Queue的執行優先級要使用dispatch_set_target_queue函數。它有兩個參數,第一個參數是指定要變更執行優先級的Dispatch Queue;第二個參數是指定要使用的執行優先級相同優先級的Global Dispatch Queue為第二個參數。
4、dispatch_after:延遲執行
5、dispatch_group_notify:是把多個處理全部結束后再執行結束處理。最后可以用dispatch_group_notify(group名稱)執行結束處理。
6、dispatch_group_wait:等待全部處理執行結束。
7、dispatch_barrier_async:會等待追加到并發派遣隊列上的并行執行的處理全部結束之后,再將制定的函數處理追加到并發派遣隊列。(有點類似于addDepency)先處理前面的幾個操作,然后遇到barrier后只執行1個barrier追加的處理,然后再繼續執行后面的處理。
8、dispatch_apply:該函數按照指定的次序將指定的Block追加到指定的Dispatch Queue中,并等待全部處理執行結束。
9、dispatch_suspend/dispatch_resume:用于有時候不希望執行以追加的處理。
10、dispatch_once:保證在應用程序執行中只執行一次指定處理。
新聞熱點
疑難解答