GCD,Grand Central Dispatch,iOS中常用的多線程技術,GCD提供C風格的API,相對NSOperationQueue以及NSThread,它更加的簡單易用且功能強大.
注意:現(xiàn)在dispatc_group_t,dispatch_queue_t, dispatch_semaphore_t等已經(jīng)被ARC管理,無需要手動release.
隊列 dispatch_queue_t
GCD提供兩種隊列Serial Dispatch Queue(串行隊列),Concurrent Dispatch Queue(并發(fā)隊列). 使用APIdispatch_queue_create創(chuàng)建.
dispatch_queue_t requestHeaderModificationQueue = dispatch_queue_create("requestHeaderModificationQueue", DISPATCH_QUEUE_CONCURRENT);
第一個參數(shù)為隊列的名字, 也可以寫為NULL,不過為了調(diào)試推薦指定對列名字.
第二個參數(shù)為DISPATCH_QUEUE_CONCURRENT或DISPATCH_QUEUE_SERIAL,用于指定隊列的類型.
dispatch_async(requestHeaderModificationQueue, ^{
.........
});
dispatch_release(requestHeaderModificationQueue);
GCD的隊列,必須由程序員手動進行引用計數(shù)的管理,當隊列需要釋放的時候,要手動的調(diào)用dispatch_release. 上面的代碼不會立即釋放隊列,因為block強引用了requestHeaderModificationQueue,會等block中的任務執(zhí)行完畢才會釋放隊列.
同時GCD提供dispatch_get_main_queue()和dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)可以便捷的獲取主線程和后臺線程.
向隊列中追加任務 dispatch_async和dispatch_sync
dispatch_async(requestHeaderModificationQueue, ^{
.........
});
dispatch_sync(requestHeaderModificationQueue, ^{
.........
});
使用dispatch_async和dispatch_sync向隊列中追加任務.
dispatch_async.異步執(zhí)行,并不會阻塞當前的線程,而是立即向下執(zhí)行.
dispatch_sync同步執(zhí)行,會阻塞當前線程,等待block中的任務執(zhí)行完畢,程序才會繼續(xù)向下執(zhí)行. 所以要避免在主線程中使用dispatch_sync
disaptch_after
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
...
});
上面的代碼意思為在5秒后執(zhí)行block中的任務.
dispatch_after 函數(shù)接受三個參數(shù)
1.第一個參數(shù)是指定時間,用的是 dispatch_time_t 類型的值. 使用dispatch_time 或者 dispatch_walltime函數(shù)生成.
dispatch_time函數(shù)能夠獲取從第一個參數(shù)dispatch_time_t類型的值,到第二個參數(shù)指定的毫秒單位時間后的時間. 如上例,第二個參數(shù)為5 * NSEC_PER_SEC毫秒也就是5秒.
2.第二個參數(shù)指定要追加任務的隊列.
dispatch_group
dispatch_group_t group = dispatch_group_create()
使用函數(shù)dispatch_group_create創(chuàng)建.
dispatch_group同樣需要程序員手動的管理引用計數(shù). 同dispatch_queue.
dispatch_group同樣有同步執(zhí)行和異步執(zhí)行兩個函數(shù):dispatch_group_async和dispatch_group_sync.
dispatch_group_async(<#dispatch_group_t _Nonnull group#>, <#dispatch_queue_t _Nonnull queue#>, <#^(void)block#>)
比起dispatch_queue的對出一個參數(shù),指定該block屬于指定的dispatch_group_t.
dispatch_group_notify
如果存在多個任務或者多個隊列,想要在所有的任務執(zhí)行完成后,執(zhí)行指定的操作,可以使用dispatch_group_notify.
dispatch_group_notify會監(jiān)聽指定的group,在所有任務執(zhí)行完成后,將指定的任務加入指定的隊列中.
dispatch_queue_t queue = dispatch_queue_create("xxx.aaa.ccc", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{
// ...
});
dispatch_group_async(group, queue, ^{
// ...
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
});
dispatch_group_notify
dispatch_group_wait
long result = dispatch_group_wait(group, dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC));
if (result == 0) {
NSLog(@"group全部執(zhí)行");
}else{
NSLog(@"group并沒有全部執(zhí)行");
}
一般來說,線程有三個狀態(tài).
- 運行,running,此刻線程正在運行
- 等待,waiting,此刻線程正在等待某一時間發(fā)生,無法執(zhí)行.
-
就緒,ready,此刻線程可以立即執(zhí)行,但是cpu已經(jīng)被占用.
thread_transform.png
操作系統(tǒng)按照優(yōu)先級或者平均分配給每個線程執(zhí)行時間. 當該線程分配的時間片未用完之前,線程開始等待某事件, 它就會等待狀態(tài). 每當一個線程離開運行狀態(tài)時,操作系統(tǒng)會選擇一個其他的就緒線程立即執(zhí)行.
dispatch_group_wait函數(shù)會使當前線程處于等待狀態(tài),并不返回.直到指定的group中的任務全部完成或者指定的時間到達后. 如上例子,group任務全部完成或者5秒之后,函數(shù)返回,如果group中的任務全部完成,將會返回0 ,否則返回非0.
當時間指定為DISPATCH_TIME_FOREVER意為永久等待,直到group中的任務全部完成.
dispatch_barrier_sync
dispatch_barrier_sync(queue, ^{
...
});
dispatch_barrier_sync可以理解為柵欄函數(shù),在該block加入隊列前加入queue的任務全部執(zhí)行完之后再去執(zhí)行該任務. 然后才會執(zhí)行后面加入的任務. 像一個柵欄一樣,把前后的任務隔離開. 可以用來在并發(fā)隊列中控制任務順序.
dispatch_suspend和dispatch_resume
隊列的掛起以及恢復.
dispatch_semaphore_t
在使用并發(fā)隊列執(zhí)行多個任務時,任務的完成時間以及順序并不能控制,可以使用dispatch_barrier_sync和dispatch_group_notify. 這里還有另外一個方法,那就是dispatch_semaphore_t
Dispatch Semaphore 是持有計數(shù)的信號,該計數(shù)是多線程編程中的計數(shù)類型的信號. 在Dispatch Semaphore中,計數(shù)為0時等待,計數(shù)為大于或者等于1時信號減去1而不對等待.
dispatch_semaphore_t semphore = dispatch_semaphore_create(1);
result = dispatch_semaphore_wait(semphore, DISPATCH_TIME_FOREVER);
dispatch_semaphore_signal(semphore);
dispatch_release(semphore);
以以上代碼為例
第一句,創(chuàng)建一個Dispatch Semaphore并且制定信號量為1
第二句,永久等待Dispatch Semaphore的信號量大于0,然后返回.代碼鄉(xiāng)下執(zhí)行.
第三句,執(zhí)行完任務后,將Dispatch Semaphore的計數(shù)值加1
第四句,如果該Dispatch Semaphore結束使用,那么手動釋放.
dispatch_once_t
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
<#code to be executed once#>
});
dispatch_once函數(shù)保證應用程序運行中,即使在多線層環(huán)境下,也只執(zhí)行一次指定的任務.常常用來被使用生成單例.
