全稱:Grand Central Dispatch
簡介:GCD是對(duì)多線程、多核開發(fā)的比較完整的封裝琳拨。在使用GCD的時(shí)候,系統(tǒng)會(huì)自動(dòng)根據(jù)CPU的使用情況進(jìn)行調(diào)度,GCD是一個(gè)簡單易用坚冀,效果很好地多線程、多核開發(fā)工具鉴逞。
dispatch_queue_t记某,GCD隊(duì)列
dispatch_async,異步操作构捡。
dispatch_sync液南,同步操作。
dispatch_apply(,,) 勾徽。
dispatch_after(,,)滑凉,延時(shí)。
dispatch_barrier_async(,);
dispatch_barrier_sync(,);
dispatch_queue_set_specific捂蕴,就是向指定隊(duì)列里面設(shè)置一個(gè)標(biāo)識(shí)譬涡。
dispatch_get_specific,就是在當(dāng)前隊(duì)列中取出標(biāo)識(shí)
dispatch_suspend/dispatch_resume
dispatch_once啥辨,一次執(zhí)行涡匀。
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
? ? ? ? 系統(tǒng)本身有兩個(gè)隊(duì)列陨瘩,dispatch_get_global_queue(,)腕够,全局隊(duì)列;dispatch_get_main_queue(),主隊(duì)列舌劳。同時(shí)帚湘,用戶可以自己創(chuàng)建隊(duì)列,dispatch_queue_create(,).
? ? ? ? 隊(duì)列的優(yōu)先級(jí)甚淡,分高級(jí)大诸、低級(jí)、默認(rèn)和后臺(tái)贯卦,DISPATCH_QUEUE_PRIORITY_DEFAULT(0)為默認(rèn)资柔,DISPATCH_QUEUE_PRIORITY_HIGH(2)為高,DISPATCH_QUEUE_PRIORITY_LOW(-2)為低撵割,DISPATCH_QUEUE_PRIORITY_BACKGROUND為后臺(tái)贿堰。
? ? ? ? dispatch_get_current_queue(void),得到當(dāng)前隊(duì)列,只能作為調(diào)試手段啡彬,已被廢棄羹与。
? ? ? ? 創(chuàng)建隊(duì)列時(shí),存在兩種Dispatch Queue,一種是等待現(xiàn)在執(zhí)行中處理的Serial Dispatch Queue,另一種是不等待現(xiàn)在執(zhí)行中處理的Concurrent Dispatch Queue庶灿。避免數(shù)據(jù)競爭這種情況纵搁,用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);
? ? ? ? 兩種創(chuàng)建方式的區(qū)別是往踢,create函數(shù)的第二個(gè)參數(shù)不一樣诡渴。
? ? ? ? 通過dispatch_queue_create函數(shù)生成的Dispatch Queue在使用結(jié)束后通過dispatch_release函數(shù)釋放dispatch_release(myConcurrentDispatchQueue);
? ? ? ? 其中,dispatch_get_main_queue()是Serial Dispatch Queue菲语;dispatch_get_global_queue(,)是Concurrent Dispatch Queue妄辩。
二:dispatch_async
? ? ? ? 提交任務(wù)后立刻返回,在后臺(tái)隊(duì)列中執(zhí)行提交的代碼塊山上。
? ? ? ? dispatch_async(,) 開啟一個(gè)異步操作眼耀,第一個(gè)參數(shù)是指定一個(gè)gcd隊(duì)列,第二個(gè)參數(shù)是分配一個(gè)處理事務(wù)的程序塊到該隊(duì)列佩憾。
? ? ? ? dispatch_async(dispatch_get_global(0,0),^{
? ? ? ? ? ? ? ? //處理耗時(shí)操作的代碼塊
? ? ? ? ? ? ? ? //處理完成哮伟,通知主線程刷新
? ? ? ? ? ? ? ? dispatch_async(dispatch_get_main_queue(),^{
? ? ? ? ? ? ? ? //回調(diào),或者說是通知主線程刷新
? ? ? ? ? ? ? ? });
? ? ? ? });
? ? ? ? NSLog(@"");
? ? ? ? 提交任務(wù)后會(huì)立即執(zhí)行l(wèi)og妄帘。
? ? ? ? 開發(fā)者只需要定義想執(zhí)行的任務(wù)并追加到適當(dāng)?shù)腄ispatch Queue 中楞黄,GCD就能生成必要的線程并計(jì)劃執(zhí)行任務(wù)。所以抡驼,開發(fā)者操作的是隊(duì)列鬼廓,系統(tǒng)會(huì)自己創(chuàng)建線程,管理線程致盟。
三:dispatch_sync
? ? ? ? 提交完任務(wù)碎税,等任務(wù)完成后才會(huì)返回尤慰。
? ? ? ? dispatch_sync(,) 開啟一個(gè)異步操作,第一個(gè)參數(shù)是指定一個(gè)gcd隊(duì)列雷蹂,第二個(gè)參數(shù)是分配一個(gè)處理事務(wù)的程序塊到該隊(duì)列伟端。
? ? ? ? 使用時(shí)會(huì)阻塞后續(xù)代碼執(zhí)行,所以都沒有用的必要了匪煌。
四:dispatch_apply
? ? ? ? dispatch_apply類似一個(gè)for循環(huán)责蝠,會(huì)在指定的dispatch queue中運(yùn)行block任務(wù)n次。dispatch_apply是一個(gè)同步調(diào)用萎庭,block任務(wù)執(zhí)行n次后才返回玛歌。
實(shí)例:
? ? ? ? dispatch_apply(5,dispatch_get_global_queue(-2,0), ^(size_ti) {
? ? ? ? ? ? ? ? NSLog(@"%@我開始執(zhí)行%zu times",[NSThreadcurrentThread],i+1);
? ? ? ? });
? ? ? ? NSLog(@"hello");
? ? ? ? 會(huì)順序打印1,2擎椰,3,4创肥,5达舒,然后打印hello。
? ? ? ? 如果放在dispatch_async中執(zhí)行叹侄,打印順序未定巩搏。
? ? ? ? dispatch_async(dispatch_get_global_queue(0,0), ^{
? ? ? ? ? ? ? ? dispatch_apply(5,dispatch_get_global_queue(-2,0), ^(size_ti) {
? ? ? ? ? ? ? ? NSLog(@"%@我開始執(zhí)行%zu times",[NSThreadcurrentThread],i+1);
? ? ? ? ? ? ? ? });
? ? ? ? });
? ? ? ? NSLog(@"hello");
? ? ? ? 會(huì)先打印hello,再打印數(shù)字趾代。但打印的數(shù)字順序未定贯底。
五:dispatch_after
? ? ? dispatch_after(,,)能把我們添加進(jìn)隊(duì)列的任務(wù)延時(shí)執(zhí)行,原理是在指定時(shí)間后追加任務(wù)處理到隊(duì)列中撒强,并不是在指定時(shí)間后執(zhí)行處理禽捆。該方法的第一個(gè)參數(shù)是時(shí)間dispatch_time_t,第二個(gè)參數(shù)是dispatch_queue飘哨,第三個(gè)參數(shù)是要執(zhí)行的代碼塊胚想。
? ? ? ? dispatch_time_t有兩種形式的構(gòu)造方式,第一種相對(duì)時(shí)間:DISPATCH_TIME_NOW表示現(xiàn)在芽隆,NSEC_PER_SEC表示的是秒數(shù)浊服,它還提供了NSEC_PER_MSEC表示毫秒第二種是絕對(duì)時(shí)間,通過dispatch_walltime函數(shù)來獲取胚吁,dispatch_walltime需要使用一個(gè)timespec的結(jié)構(gòu)體來得到dispatch_time_t牙躺。
六:dispatch_barrier_async
? ? ? ? 將自己的任務(wù)插入到隊(duì)列之后,不會(huì)等待自己的任務(wù)結(jié)束腕扶,它會(huì)繼續(xù)把后面的任務(wù)插入到隊(duì)列孽拷,然后等待自己的任務(wù)結(jié)束后才執(zhí)行后面任務(wù)。
實(shí)例:
? ? ? ? //1 創(chuàng)建并發(fā)隊(duì)列
? ? ? ? dispatch_queue_tconcurrentQueue = dispatch_queue_create("concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
? ? ? ? //2 向隊(duì)列中添加任務(wù)
? ? ? ? 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的執(zhí)行一定是在barrier的后面。
使用場景:
? ? ? ? 訪問數(shù)據(jù)庫使用环形,寫入操作策泣。可以實(shí)現(xiàn)高效率的數(shù)據(jù)庫訪問和文件訪問抬吟。
七:dispatch_barrier_sync(,)
? ? ? ? 將自己的任務(wù)插入到隊(duì)列的時(shí)候萨咕,需要等待自己的任務(wù)結(jié)束之后才會(huì)繼續(xù)插入被寫在它后面的任務(wù),然后執(zhí)行它們火本。
? ? ? ? //1 創(chuàng)建并發(fā)隊(duì)列
? ? ? ? dispatch_queue_tconcurrentQueue = dispatch_queue_create("concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
? ? ? ? //2 向隊(duì)列中添加任務(wù)
? ? ? ? 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執(zhí)行了揍魂,后續(xù)的才會(huì)執(zhí)行桨醋。
八:dispatch_queue_set_specific
? ? ? ? dispatch_queue_set_specific(queue, queueKey, &queueKey,NULL);
? ? ? ? 就是給queue隊(duì)列設(shè)置一個(gè)queueKey標(biāo)識(shí)。
九:dispatch_get_specific
? ? ? ?dispatch_get_specific(key);
? ? ? ? 判斷當(dāng)前隊(duì)列有無key標(biāo)識(shí)现斋。
實(shí)例:
? ? ? ? staticvoid* key =@"key111";
? ? ? ? dispatch_queue_set_specific(dispatch_get_global_queue(0,0),key, &key,NULL);
? ? ? ? if(dispatch_get_specific(key)) {
? ? ? ? ? ? ? ? NSLog(@"找到了標(biāo)識(shí)隊(duì)列");
? ? ? ? }
? ? ? ? dispatch_async(dispatch_get_global_queue(0,0), ^{
? ? ? ? if(dispatch_get_specific(key)) {
? ? ? ? ? ? ? ? NSLog(@"找到了標(biāo)識(shí)隊(duì)列1");
? ? ? ? }
? ? ? ? });
? ? ? ? 打印結(jié)果:找到了標(biāo)識(shí)隊(duì)列1讨盒。
十:dispatch_suspend/dispatch_resume
? ? ? ? 當(dāng)追加大量的處理到Dispatch Queue時(shí),再追加處理的過程中步责,有時(shí)希望不執(zhí)行已追加的處理返顺,例如演算結(jié)果被Block截取時(shí),一些處理會(huì)對(duì)這個(gè)演算結(jié)果造成影響蔓肯。在這種情況下遂鹊,只要掛起DispatchQueue即可,當(dāng)可以執(zhí)行時(shí)再恢復(fù)蔗包。
? ? ? ? dispatch_suspend(queue);掛起Dispatch Queue.
? ? ? ? dispatch_resume(queue);恢復(fù)指定的Dispatch Queue.
十一:dispatch_once
? ? ? ? 保證在應(yīng)用程序執(zhí)行中只執(zhí)行一次指定處理的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);
? ? ? ? });