全稱:Grand Central Dispatch
簡介:GCD是對多線程、多核開發的比較完整的封裝。在使用GCD的時候,系統會自動根據CPU的使用情況進行調度,GCD是一個簡單易用,效果很好地多線程、多核開發工具。
dispatch_queue_t,GCD隊列
dispatch_async,異步操作。
dispatch_sync,同步操作。
dispatch_apply(,,) 。
dispatch_after(,,),延時。
dispatch_barrier_async(,);
dispatch_barrier_sync(,);
dispatch_queue_set_specific,就是向指定隊列里面設置一個標識。
dispatch_get_specific,就是在當前隊列中取出標識
dispatch_suspend/dispatch_resume
dispatch_once,一次執行。
Dispatch I/O,文件讀寫操作。
dispatch_block_t
dispatch_block_create(dispatch_block_flags_t flags, dispatch_block_t block);
dispatch_block_t
dispatch_block_create_with_qos_class(dispatch_block_flags_tflags,
dispatch_qos_class_tqos_class,intrelative_priority,
dispatch_block_t block);
一:dispatch_queue_t
? ? ? ? 系統本身有兩個隊列,dispatch_get_global_queue(,),全局隊列;dispatch_get_main_queue(),主隊列。同時,用戶可以自己創建隊列,dispatch_queue_create(,).
? ? ? ? 隊列的優先級,分高級、低級、默認和后臺,DISPATCH_QUEUE_PRIORITY_DEFAULT(0)為默認,DISPATCH_QUEUE_PRIORITY_HIGH(2)為高,DISPATCH_QUEUE_PRIORITY_LOW(-2)為低,DISPATCH_QUEUE_PRIORITY_BACKGROUND為后臺。
? ? ? ? dispatch_get_current_queue(void),得到當前隊列,只能作為調試手段,已被廢棄。
? ? ? ? 創建隊列時,存在兩種Dispatch Queue,一種是等待現在執行中處理的Serial Dispatch Queue,另一種是不等待現在執行中處理的Concurrent Dispatch Queue。避免數據競爭這種情況,用Serial Dispatch Queue。
生成Serial Dispatch Queue:
? ? ? ? dispatch_queue_t mySerialDispatchQueue =dispatch_queue_create("MySerialDispatchQueue",NULL);
生成ConcurrentDispatchQueue:
? ? ? ? dispatch_queue_t myConcurrentDispatchQueue = dispatch_queue_create("MyConcurrentDispatchQueue",DISPATCH_QUEUE_CONCURRENT);
? ? ? ? 兩種創建方式的區別是,create函數的第二個參數不一樣。
? ? ? ? 通過dispatch_queue_create函數生成的Dispatch Queue在使用結束后通過dispatch_release函數釋放dispatch_release(myConcurrentDispatchQueue);
? ? ? ? 其中,dispatch_get_main_queue()是Serial Dispatch Queue;dispatch_get_global_queue(,)是Concurrent Dispatch Queue。
二:dispatch_async
? ? ? ? 提交任務后立刻返回,在后臺隊列中執行提交的代碼塊。
? ? ? ? dispatch_async(,) 開啟一個異步操作,第一個參數是指定一個gcd隊列,第二個參數是分配一個處理事務的程序塊到該隊列。
? ? ? ? dispatch_async(dispatch_get_global(0,0),^{
? ? ? ? ? ? ? ? //處理耗時操作的代碼塊
? ? ? ? ? ? ? ? //處理完成,通知主線程刷新
? ? ? ? ? ? ? ? dispatch_async(dispatch_get_main_queue(),^{
? ? ? ? ? ? ? ? //回調,或者說是通知主線程刷新
? ? ? ? ? ? ? ? });
? ? ? ? });
? ? ? ? NSLog(@"");
? ? ? ? 提交任務后會立即執行log。
? ? ? ? 開發者只需要定義想執行的任務并追加到適當的Dispatch Queue 中,GCD就能生成必要的線程并計劃執行任務。所以,開發者操作的是隊列,系統會自己創建線程,管理線程。
三:dispatch_sync
? ? ? ? 提交完任務,等任務完成后才會返回。
? ? ? ? dispatch_sync(,) 開啟一個異步操作,第一個參數是指定一個gcd隊列,第二個參數是分配一個處理事務的程序塊到該隊列。
? ? ? ? 使用時會阻塞后續代碼執行,所以都沒有用的必要了。
四:dispatch_apply
? ? ? ? dispatch_apply類似一個for循環,會在指定的dispatch queue中運行block任務n次。dispatch_apply是一個同步調用,block任務執行n次后才返回。
實例:
? ? ? ? dispatch_apply(5,dispatch_get_global_queue(-2,0), ^(size_ti) {
? ? ? ? ? ? ? ? NSLog(@"%@我開始執行%zu times",[NSThreadcurrentThread],i+1);
? ? ? ? });
? ? ? ? NSLog(@"hello");
? ? ? ? 會順序打印1,2,3,4,5,然后打印hello。
? ? ? ? 如果放在dispatch_async中執行,打印順序未定。
? ? ? ? dispatch_async(dispatch_get_global_queue(0,0), ^{
? ? ? ? ? ? ? ? dispatch_apply(5,dispatch_get_global_queue(-2,0), ^(size_ti) {
? ? ? ? ? ? ? ? NSLog(@"%@我開始執行%zu times",[NSThreadcurrentThread],i+1);
? ? ? ? ? ? ? ? });
? ? ? ? });
? ? ? ? NSLog(@"hello");
? ? ? ? 會先打印hello,再打印數字。但打印的數字順序未定。
五:dispatch_after
? ? ? dispatch_after(,,)能把我們添加進隊列的任務延時執行,原理是在指定時間后追加任務處理到隊列中,并不是在指定時間后執行處理。該方法的第一個參數是時間dispatch_time_t,第二個參數是dispatch_queue,第三個參數是要執行的代碼塊。
? ? ? ? dispatch_time_t有兩種形式的構造方式,第一種相對時間:DISPATCH_TIME_NOW表示現在,NSEC_PER_SEC表示的是秒數,它還提供了NSEC_PER_MSEC表示毫秒第二種是絕對時間,通過dispatch_walltime函數來獲取,dispatch_walltime需要使用一個timespec的結構體來得到dispatch_time_t。
六:dispatch_barrier_async
? ? ? ? 將自己的任務插入到隊列之后,不會等待自己的任務結束,它會繼續把后面的任務插入到隊列,然后等待自己的任務結束后才執行后面任務。
實例:
? ? ? ? //1 創建并發隊列
? ? ? ? dispatch_queue_tconcurrentQueue = dispatch_queue_create("concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
? ? ? ? //2 向隊列中添加任務
? ? ? ? dispatch_async(concurrentQueue, ^{NSLog(@"1,%@",[NSThread currentThread]);? ? });
? ? ? ? dispatch_async(concurrentQueue, ^{NSLog(@"2,%@",[NSThread currentThread]);? ? });
? ? ? ? dispatch_async(concurrentQueue, ^{NSLog(@"3,%@",[NSThread currentThread]);? ? });? ??
? ? ? ? dispatch_barrier_async(concurrentQueue, ^{? ? ? ? [NSThread sleepForTimeInterval:1.0];NSLog(@"barrier");? ? });
? ? ? ? NSLog(@"aa");
? ? ? ? ?dispatch_async(concurrentQueue, ^{NSLog(@"4,%@",[NSThreadcurrentThread]);? ? });
? ? ? ? NSLog(@"bb");
? ? ? ? dispatch_async(concurrentQueue, ^{NSLog(@"5,%@",[NSThreadcurrentThread]);? ? });
? ? ? ? 打印順序是:3,aa,1,2,bb,barrier,4,5。也就是說4,5的執行一定是在barrier的后面。
使用場景:
? ? ? ? 訪問數據庫使用,寫入操作。可以實現高效率的數據庫訪問和文件訪問。
七:dispatch_barrier_sync(,)
? ? ? ? 將自己的任務插入到隊列的時候,需要等待自己的任務結束之后才會繼續插入被寫在它后面的任務,然后執行它們。
? ? ? ? //1 創建并發隊列
? ? ? ? dispatch_queue_tconcurrentQueue = dispatch_queue_create("concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
? ? ? ? //2 向隊列中添加任務
? ? ? ? dispatch_async(concurrentQueue, ^{NSLog(@"1,%@",[NSThread currentThread]);? ? });
? ? ? ? dispatch_async(concurrentQueue, ^{NSLog(@"2,%@",[NSThread currentThread]);? ? });
? ? ? ? dispatch_async(concurrentQueue, ^{NSLog(@"3,%@",[NSThread currentThread]);? ? });? ??
? ? ? ? dispatch_barrier_sync(concurrentQueue, ^{? ? ? ? [NSThread sleepForTimeInterval:1.0];NSLog(@"barrier");? ? });
? ? ? ? NSLog(@"aa");
? ? ? ? dispatch_async(concurrentQueue, ^{NSLog(@"4,%@",[NSThread currentThread]);? ? });
? ? ? ? NSLog(@"bb");
? ? ? ? dispatch_async(concurrentQueue, ^{NSLog(@"5,%@",[NSThreadcurrentThread]);? ? });
? ? ? ? 打印順序是:3,1,2,barrier,aa,bb,4,5。也就是說只有barrier執行了,后續的才會執行。
八:dispatch_queue_set_specific
? ? ? ? dispatch_queue_set_specific(queue, queueKey, &queueKey,NULL);
? ? ? ? 就是給queue隊列設置一個queueKey標識。
九:dispatch_get_specific
? ? ? ?dispatch_get_specific(key);
? ? ? ? 判斷當前隊列有無key標識。
實例:
? ? ? ? staticvoid* key =@"key111";
? ? ? ? dispatch_queue_set_specific(dispatch_get_global_queue(0,0),key, &key,NULL);
? ? ? ? if(dispatch_get_specific(key)) {
? ? ? ? ? ? ? ? NSLog(@"找到了標識隊列");
? ? ? ? }
? ? ? ? dispatch_async(dispatch_get_global_queue(0,0), ^{
? ? ? ? if(dispatch_get_specific(key)) {
? ? ? ? ? ? ? ? NSLog(@"找到了標識隊列1");
? ? ? ? }
? ? ? ? });
? ? ? ? 打印結果:找到了標識隊列1。
十:dispatch_suspend/dispatch_resume
? ? ? ? 當追加大量的處理到Dispatch Queue時,再追加處理的過程中,有時希望不執行已追加的處理,例如演算結果被Block截取時,一些處理會對這個演算結果造成影響。在這種情況下,只要掛起DispatchQueue即可,當可以執行時再恢復。
? ? ? ? dispatch_suspend(queue);掛起Dispatch Queue.
? ? ? ? dispatch_resume(queue);恢復指定的Dispatch Queue.
十一:dispatch_once
? ? ? ? 保證在應用程序執行中只執行一次指定處理的API。用來初始化。
? ? ? ? static dispatch_once_tpred;
? ? ? ? dispatch_once(&pred, ^{
? ? ? ? });
十二:Dispatch I/O
? ? ? ? 讀寫文件,提高文件讀取速度。
? ? ? ? pipe_q = dispatch_queue_create("PipeQ",NULL);
? ? ? ? pipe_channel = dispatch_io_create(DISPATCH_IO_STREAM, fd,pipe_q, ^(interror) {
? ? ? ? close(fd);
? ? ? ? });