GCD 的使用

Serial vs. Concurrent 串行 vs. 并發(fā)

這些術(shù)語描述當任務相對于其它任務被執(zhí)行,任務串行執(zhí)行就是每次只有一個任務被執(zhí)行,任務并發(fā)執(zhí)行就是在同一時間可以有多個任務被執(zhí)行。
Synchronous vs. Asynchronous 同步 vs. 異步

在 GCD 中,這些術(shù)語描述當一個函數(shù)相對于另一個任務完成,此任務是該函數(shù)要求 GCD 執(zhí)行的。一個同步函數(shù)只在完成了它預定的任務后才返回。

一個異步函數(shù),剛好相反,會立即返回,預定的任務會完成但不會等它完成。因此,一個異步函數(shù)不會阻塞當前線程去執(zhí)行下一個函數(shù)。
Deadlock 死鎖
兩個(有時更多)東西——在大多數(shù)情況下,是線程——所謂的死鎖是指它們都卡住了,并等待對方完成或執(zhí)行其它操作。第一個不能完成是因為它在等待第二個的完成。但第二個也不能完成,因為它在等待第一個的完成。
(https://github.com/nixzhu/dev-blog/blob/master/2014-04-19-grand-central-dispatch-in-depth-part-1.md#thread-safe-線程安全)Thread Safe 線程安全
線程安全的代碼能在多線程或并發(fā)任務中被安全的調(diào)用,而不會導致任何問題(數(shù)據(jù)損壞,崩潰,等)。線程不安全的代碼在某個時刻只能在一個上下文中運行。一個線程安全代碼的例子是 NSDictionary
。你可以在同一時間在多個線程中使用它而不會有問題。另一方面,NSMutableDictionary
就不是線程安全的,應該保證一次只能有一個線程訪問它。
Queues 隊列
GCD 提供有 dispatch queues
來處理代碼塊,這些隊列管理你提供給 GCD 的任務并用 FIFO 順序執(zhí)行這些任務。這就保證了第一個被添加到隊列里的任務會是隊列中第一個開始的任務,而第二個被添加的任務將第二個開始,如此直到隊列的終點。
所有的調(diào)度隊列(dispatch queues)自身都是線程安全的,你能從多個線程并行的訪問它們。當你了解了調(diào)度隊列如何為你自己代碼的不同部分提供線程安全后,GCD的優(yōu)點就是顯而易見的。關(guān)于這一點的關(guān)鍵是選擇正確類型的調(diào)度隊列和正確的調(diào)度函數(shù)來提交你的工作。
在本節(jié)你會看到兩種調(diào)度隊列,都是由 GCD 提供的,然后看一些描述如何用調(diào)度函數(shù)添加工作到隊列的例子。
[

](https://github.com/nixzhu/dev-blog/blob/master/2014-04-19-grand-central-dispatch-in-depth-part-1.md#serial-queues-串行隊列)Serial Queues 串行隊列
串行隊列中的任務一次執(zhí)行一個,每個任務只在前一個任務完成時才開始。而且,你不知道在一個 Block 結(jié)束和下一個開始之間的時間長度,如下圖所示:

serial Queue.png

同步:不會開啟新的線程,在本線程中執(zhí)行,異步:具有開啟子線程的能力,但是會不會開啟就要看自己加的那個隊列了,如果隊列是主隊列,就不會創(chuàng)建子線程,所有的任務會在主隊列中完成,如果是異步,且在全局隊列中會首先創(chuàng)建一個子線程,每一個block里的代碼,就是一個任務,將每一個任務加載到一個隊列中,這個隊列是全局隊列的話,并且是異步的話,會產(chǎn)生多個子線程,全局隊列就是并發(fā)的意思,隊列有一個先進先出的特點,當自己有一個在主線程中執(zhí)行的任務的時候,如果eg:
[sef creatsyncQueue]//主線程執(zhí)行
+(void)creatsyncQueue
[
dispatch_sync(get_main_queue()){
nslog(“”);//死鎖樂

將sync換成async不會死鎖,因為這時候async不會先執(zhí)行里邊的代碼

}
步驟: 1 創(chuàng)建隊列 2 創(chuàng)建任務 3 將任務加到隊列中,同步還是異步

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 下載圖片
UIImage *image = nil;
1 dispatch_async(dispatch_get_main_queue(), ^{
// 回到主線程

//在這使用主隊列會將在主線程中執(zhí)行,為啥使用異步呢?
});

下面是一個關(guān)于在 dispatch_async 上如何以及何時使用不同的隊列類型的快速指導:

  • 自定義串行隊列:當你想串行執(zhí)行后臺任務并追蹤它時就是一個好選擇。這消除了資源爭用,因為你知道一次只有一個任務在執(zhí)行。注意若你需要來自某個方法的數(shù)據(jù),你必須內(nèi)聯(lián)另一個 Block 來找回它或考慮使用 dispatch_sync。

  • 主隊列(串行):這是在一個并發(fā)隊列上完成任務后更新 UI 的共同選擇。要這樣做,你將在一個 Block 內(nèi)部編寫另一個 Block 。以及,如果你在主隊列調(diào)用 dispatch_async 到主隊列,你能確保這個新任務將在當前方法完成后的某個時間執(zhí)行。

  • 并發(fā)隊列:這是在后臺執(zhí)行非 UI 工作的共同選擇。

單例:

  • (instancetype)sharedManager
    {
    static PhotoManager *sharedPhotoManager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
    sharedPhotoManager = [[PhotoManager alloc] init];
    sharedPhotoManager->_photosArray = [NSMutableArray array];
    });
    return sharedPhotoManager;
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容