日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

GCD的简介及应用

發布時間:2023/12/18 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 GCD的简介及应用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

OC中有三種多線程,分別是NSThread、NSOperationQueue、及GCD;三者使用的輕重度依次是GCD-->NSOperationQueue-->NSThread;這里就不詳細對比。

GCD這要是采用C語言語法配合Block實現,可以實現同步、異步操作;運行并行、串行隊列;同步鎖,單例、延時等。

Dispatch Queue

Dispatch Queue種類說明
Serial Dispatch Queue串行隊列
Concurrent Dispatch Queue并行隊列

系統的Queue:

GCD中提供兩個系統的Queue一個是mian_queue,一個是global_queue;兩者分別屬于串行隊列及并行隊列;

dispatch_queue_t main_queue =? dispatch_get_main_queue();dispatch_queue_t global_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

自定義Queue

dispatch_queue_t serial_queue =?dispatch_queue_create("DISPATCH_QUEUE_SERIAL", QUEUESERIAL);dispatch_queue_t concurrent_queue = dispatch_queue_create("QUEUECONCURRENT", DISPATCH_QUEUE_CONCURRENT);

async與sync

async為異步操作,不用等待執行結果,sync為同步操作,等待執行結果。

async可以異步開啟多線程隊列,包括串行隊列、并行隊列,也可以異步返回主線程刷新UI:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{//多線程操作dispatch_async(dispatch_get_main_queue(), ^{//主線程刷新UI? ? ? ? ? ??}); });

備注:異步會出現數據不同步的情況,需要實現數據的同步處理。

sync一般常配合串行隊列實現同步鎖:

dispatch_queue_t serial_queue =? dispatch_queue_create("QUEUESERIAL", DISPATCH_QUEUE_SERIAL);dispatch_sync(serial_queue, ^{});

備注:同步鎖不能用于該串行隊列的線程操作中,不然會導致線程堵塞。

suspend/resume

dispatch_suspend(queue);

掛起指定的Dispatch_Queue

dispatch_resume(queue);

恢復指定的Dispatch_Queue

Dispatch_Group

GCD中的Group可以解決異步隊列的數據不同步問題,實現同個并行隊列的回調監聽,并在隊列執行完之后調用notify通知

dispatch_group_t group = dispatch_group_create();dispatch_queue_t queue = dispatch_queue_create("CONCURRENTQUEUE", DISPATCH_QUEUE_CONCURRENT);dispatch_group_async(_group, _queue, ^{ sleep(2); NSLog(@"1");??});dispatch_group_async(_group, _queue, ^{ sleep(2); NSLog(@"2");??});dispatch_group_notify(_group, dispatch_get_main_queue(), ^{ NSLog(@"3");?});

如果不是用同一個GCD_Queue的多線程操作,可以用group_enter和group_leave實現,類似于計數器

dispatch_group_enter(_group); //+1?dispatch_group_leave(_group); //-1dispatch_group_notify(_group, dispatch_get_main_queue(), ^{?});//為0時觸發通知回調

group中的wait方法也會阻塞線程,但也隨著enter和leave的平衡(計數為0時)而失效

dispatch_group_wait(_group, dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)));//阻塞線程2秒鐘

?dispatch_barrier

?dispatch_barrier:在并行隊列中添加串行操作,實現欄柵化。

dispatch_queue_t queue = dispatch_queue_create("QUEUECONCURRENT", DISPATCH_QUEUE_CONCURRENT);dispatch_async(queue, ^{ sleep(1);NSLog(@"1");? });? ??dispatch_async(queue, ^{sleep(1);NSLog(@"2");? });dispatch_barrier_async(queue, ^{sleep(1);NSLog(@"3");? });dispatch_barrier_async(queue, ^{sleep(1);NSLog(@"4");? });?? ?dispatch_async(queue, ^{sleep(1);NSLog(@"5");? });dispatch_async(queue, ^{sleep(1);NSLog(@"6"); });

備注:先執行 1、2并行操作,再執行3、4串行操作,最后執行5、6并行操作

dispatch_semaphore

類似于鎖的作用,通過設置信號量限定當前訪問資源的最大線程量,先調用wait(降低)再調用signal(提高),信號量小于0時,處于鎖住狀態,無法訪問資源。

dispatch_semaphore_t semaphore = dispatch_semaphore_create(1); dispatch_queue_t quene = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);//任務1dispatch_async(quene, ^{dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);NSLog(@"run task 1");sleep(1);NSLog(@"complete task 1");dispatch_semaphore_signal(semaphore); });//任務2dispatch_async(quene, ^{dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);NSLog(@"run task 2");sleep(1);NSLog(@"complete task 2");dispatch_semaphore_signal(semaphore); });//任務3dispatch_async(quene, ^{dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);NSLog(@"run task 3");sleep(1);NSLog(@"complete task 3");dispatch_semaphore_signal(semaphore); }); }// 信號量為1,依次執行Task1、Task2、Task3。

阻塞當前線程,等待異步事件執行完成

dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{sleep(1);dispatch_semaphore_signal(semaphore); });dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);// 在wait之后阻塞當前線程,在signal之后恢復執行

dispatch_once

單例模式,確保應用只執行一次once中的代碼塊。

static NSArray* dataArr;static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{dataArr = @[@"1",@"2",@"3"];});

dispatch_after

延時處理,類似于NSTimer,不過只是單次,不能設置循環

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{//延時兩秒 });

dispatch_source?

事件源處理,一般應用于定時器,具有高精準度,不會受到RunLoopMode切換的影響(default->Tracking)。NSTimer(有一定的誤差)、CADisplayLink(高精準度,適用于高頻的動畫效果),NSTimer與CADisplayLink都會受到RunLoopMode切換的影響。

@implementation GCDSource- (instancetype)initWithTimeInterval:(NSTimeInterval)timeInterval repeats:(BOOL)repeats timerBlock:(void(^)(void))timerBlock {self = [super init];if (self) {_timeInterval = timeInterval;_repeats = repeats;self.timerBlock = timerBlock;[self initTimer];}return self; }- (void)initTimer {dispatch_queue_t timerQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);dispatch_queue_t blockQueue = dispatch_get_main_queue();self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, timerQueue);dispatch_source_set_timer(_timer, dispatch_walltime(NULL, 0), _timeInterval * NSEC_PER_SEC, 0);dispatch_source_set_event_handler(_timer, ^{dispatch_async(blockQueue, ^{self.timerBlock();});if (_repeats == NO) {[self stopTimer];}});dispatch_resume(_timer); }- (void)pauseTimer {if(self.timer){dispatch_suspend(_timer);} }- (void)resumeTimer {if(self.timer){dispatch_resume(_timer);} }- (void)stopTimer {if(self.timer){dispatch_source_cancel(_timer);_timer = nil;} }- (void)dealloc {[self stopTimer]; }@end

dispatch_target

使queue的優先級與目標queue相同

如果將多個串行的queue使用dispatch_set_target_queue指定到了同一目標,那么著多個串行queue在目標queue上就是同步執行的,不再是并行執行。

dispatch_queue_t targetQueue = dispatch_queue_create("targetQueue", DISPATCH_QUEUE_SERIAL);dispatch_queue_t queue1 = dispatch_queue_create("queue1", DISPATCH_QUEUE_SERIAL);dispatch_queue_t queue2 = dispatch_queue_create("queue2", DISPATCH_QUEUE_SERIAL);dispatch_queue_t queue3 = dispatch_queue_create("queue3", DISPATCH_QUEUE_SERIAL);dispatch_set_target_queue(queue1, targetQueue);dispatch_set_target_queue(queue2, targetQueue);dispatch_async(queue1, ^{sleep(1);NSLog(@"1");});dispatch_async(queue2, ^{sleep(1);NSLog(@"2");});dispatch_async(queue3, ^{sleep(1);NSLog(@"3"); });

備注:三個不同的串行隊列,會作為一個串行隊列的方式執行,依次輸出1,2,3

GCD對象化封裝

GCDObjective

總結

以上是生活随笔為你收集整理的GCD的简介及应用的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。