iOS相關 | GCD學習

GCD核心概念:任務和隊列

任務:在線程中執行的那段代碼。執行方式有兩種:同步執行和異步執行

* 同步執行:只能在當前線程執行,不具有開啟新線程的能力(dispatch_sync)

* 異步執行:可以在新線程中執行任務,具有開啟新線程的能力(dispatch_async)

隊列:這里的隊列指任務隊列,即用來存放任務的隊列。隊列是一種特殊的線性表,采用FIFO(先進先出)的原則,即新任務總是被插入到隊列的末尾,而讀取任務的時候總是從隊列的頭部開始讀取。每讀取一個任務,則從隊列中釋放一個任務。在GCD中有兩種隊列:串行隊列并發隊列

* 并發隊列(Concurrent Dispatch Queue):可以讓多個任務并發(同時)執行(自動開啟多個線程同時執行任務)

? ? ? ? ? 1)并發功能只有在異步(dispatch_async)函數下才有效

* 串行隊列(Serial Dispatch Queue):讓任務一個接著一個地執行(一個任務執行完畢后,再執行下一個任務)

GCD的使用步驟

1、創建一個隊列(串行隊列或并發隊列)

2、將任務添加到隊列中,然后系統就會根據任務類型執行任務(同步執行或異步執行)

1. 隊列的創建方法

可以使用dispatch_queue_create來創建對象,需要傳入兩個參數,第一個參數表示隊列的唯一標識符,用于DEBUG,可為空;第二個參數用來識別是串行隊列還是并發隊列。DISPATCH_QUEUE_SERIAL表示串行隊列,DISPATCH_QUEUE_CONCURRENT表示并發隊列。

// 串行隊列的創建方法

dispatch_queue_tqueue= dispatch_queue_create("test.queue", DISPATCH_QUEUE_SERIAL);

// 并發隊列的創建方法

dispatch_queue_tqueue= dispatch_queue_create("test.queue", DISPATCH_QUEUE_CONCURRENT);

對于并發隊列,還可以使用dispatch_get_global_queue來創建全局并發隊列。GCD默認提供了全局的并發隊列,需要傳入兩個參數。第一個參數表示隊列優先級,一般用DISPATCH_QUEUE_PRIORITY_DEFAULT。第二個參數暫時沒用,用0即可。

2. 任務的創建方法

// 同步執行任務創建方法

dispatch_sync(queue, ^{

? ? ? ? ? NSLog(@"%@",[NSThreadcurrentThread]);

? ? ? ? ? // 這里放任務代碼

});

// 異步執行任務創建方法

dispatch_async(queue, ^{

? ? ? ? ? ?NSLog(@"%@",[NSThreadcurrentThread]);

? ? ? ? ? ? // 這里放任務代碼

});

GCD基本使用

1. 并發隊列 + 同步執行

- (void) syncConcurrent{

NSLog(@"syncConcurrent---begin");

dispatch_queue_tqueue= dispatch_queue_create("test.queue", DISPATCH_QUEUE_CONCURRENT);

dispatch_sync(queue, ^{for(inti =0; i <2; ++i) {

? ? ? ? NSLog(@"1------%@",[NSThreadcurrentThread]);?

}? ? });

dispatch_sync(queue, ^{for(inti =0; i <2; ++i) {

? ? ? ? NSLog(@"2------%@",[NSThreadcurrentThread]);? ? ? ?

}? ? });

dispatch_sync(queue, ^{for(inti =0; i <2; ++i) {

? ? ? ? NSLog(@"3------%@",[NSThreadcurrentThread]);? ? ? ?

}? ? });

NSLog(@"syncConcurrent---end");}



2. GCD的延時執行方法dispatch_after

當我們需要延遲執行一段代碼時,就需要用到GCD的dispatch_after方法。

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0* NSEC_PER_SEC)), dispatch_get_main_queue(), ^{? ?

? ? ? // 2秒后異步執行這里的代碼...? NSLog(@"run-----");

});

3. GCD的一次性代碼(只執行一次)dispatch_once

我們在創建單例、或者有整個程序運行過程中只執行一次的代碼時,我們就用到了GCD的dispatch_once方法。使用dispatch_once函數能保證某段代碼在程序運行過程中只被執行1次。

staticdispatch_once_tonceToken;

dispatch_once(&onceToken, ^{

? ? ? ? ?// 只執行1次的代碼(這里面默認是線程安全的)

});

4. GCD的快速迭代方法dispatch_apply

通常我們會用for循環遍歷,但是GCD給我們提供了快速迭代的方法dispatch_apply,使我們可以同時遍歷。比如說遍歷0~5這6個數字,for循環的做法是每次取出一個元素,逐個遍歷。dispatch_apply可以同時遍歷多個數字。

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

dispatch_apply(6, queue, ^(size_tindex) {? ?

? ? ? ? ?NSLog(@"%zd------%@",index, [NSThread currentThread]);

});

5. GCD的隊列組dispatch_group

有時候我們會有這樣的需求:分別異步執行2個耗時操作,然后當2個耗時操作都執行完畢后再回到主線程執行操作。這時候我們可以用到GCD的隊列組。

我們可以先把任務放到隊列中,然后將隊列放入隊列組中。

調用隊列組的dispatch_group_notify回到主線程執行操作。

dispatch_group_t group =? dispatch_group_create();

dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{? ??

? ? ? // 執行1個耗時的異步操作});

dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{? ??

? ? ? // 執行1個耗時的異步操作

});

dispatch_group_notify(group, dispatch_get_main_queue(), ^{

? ? ? // 等前面的異步操作都執行完畢后,回到主線程...

});

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容