ios GCD將異步轉換為同步

ios GCD將異步轉換為同步

在開發(fā)中有時需要等網(wǎng)絡請求完成之后拿到數(shù)據(jù)做一些操作,而且有時是同時好幾個網(wǎng)絡請求同時發(fā)起。這時會有對異步操作進行更進一步控制的場景,不單網(wǎng)絡請求,有時一些其他本地文件,多張圖片處理等可能都會遇到這種操作,GCD中就有很多這方面處理的api

1. 利用并發(fā)隊列和柵欄函數(shù)對異步操作進行控制。

  // 創(chuàng)建隊列dispatch_queue_t queue = dispatch_queue_create("task", DISPATCH_QUEUE_CONCURRENT);

? ? // 添加任務dispatch_async(queue, ^{

? ? ? ? NSLog(@"1===task===%@", [NSThread currentThread]);

? ? });

? ? dispatch_async(queue, ^{

? ? ? ? NSLog(@"2===task===%@", [NSThread currentThread]);

? ? });

? ? dispatch_async(queue, ^{

? ? ? ? NSLog(@"3===task===%@", [NSThread currentThread]);

? ? });

? ? // 與dispatch_barrier_async區(qū)別就是它的block里代碼是否在主線程執(zhí)行dispatch_barrier_sync(queue, ^{

? ? ? ? NSLog(@"===barrier==%@", [NSThread currentThread]);

? ? });

? ? dispatch_async(queue, ^{

? ? ? ? NSLog(@"4===task===%@", [NSThread currentThread]);

? ? });

? ? dispatch_async(queue, ^{

? ? ? ? NSLog(@"5===task===%@", [NSThread currentThread]);

? ? });

? ? dispatch_async(queue, ^{

? ? ? ? NSLog(@"6===task===%@", [NSThread currentThread]);

? ? });

  上述代碼打印如下:

從打印可以看出dispatch_barrier_sync柵欄函數(shù)后 task 4,5,6 在 task1,2,3 執(zhí)行完后才執(zhí)行的。


2. 使用調(diào)度組進行分發(fā)操作dispatch_group_t,代碼如下:

1dispatch_group_t group = dispatch_group_create(); 2 3? ? dispatch_group_enter(group); 4? ? dispatch_group_enter(group); 5// 一個真實的網(wǎng)絡請求 6NSMutableDictionary *dict = [NSMutableDictionary dictionary]; 7dict[@"a"] =@"square"; 8dict[@"c"] =@"topic"; 9[MLNetService requestType:RequestTypeGet URL:kBaseUrl dict:dict sBlock:^(id result) {10NSLog(@"%@", result);11? ? ? ? dispatch_group_leave(group);12} fBlcok:^(NSError *error) {13NSLog(@"%@", error);14? ? ? ? dispatch_group_leave(group);15? ? }];1617// 一個真實的網(wǎng)絡請求18NSMutableDictionary *dict2 = [NSMutableDictionary dictionary];19dict2[@"a"] =@"square";20dict2[@"c"] =@"topic";21[MLNetService requestType:RequestTypeGet URL:kBaseUrl dict:dict2 sBlock:^(id result) {22NSLog(@"%@", result);23? ? ? ? dispatch_group_leave(group);24} fBlcok:^(NSError *error) {25NSLog(@"%@", error);26? ? ? ? dispatch_group_leave(group);27? ? }];2829//? ? dispatch_get_global_queue(0, 0)30dispatch_group_notify(group, dispatch_get_main_queue(), ^{31NSLog(@"任務完成==%@", [NSThread currentThread]);32});

上述代碼中dispatch_group_enter與dispatch_group_leave一定要成對出現(xiàn)。請求前調(diào)用?dispatch_group_enter,請求結束后調(diào)用?dispatch_group_leave ,只有當所有的 enter 都 leave后,dispatch_group_notify 的block才會執(zhí)行。所以上面代碼等兩個網(wǎng)絡請求結束后會打印任務完成。


3. 使用信號量dispatch_semaphore_t對并發(fā)進行控制

  信號量這里可以看作是資源標識,只有當它信號數(shù)大于0才可以往后面執(zhí)行,它有三個對應的 api 。

dispatch_semaphore_create創(chuàng)建一個信號,并指定初始的信號數(shù)

dispatch_semaphore_signal使對應的信號數(shù)加1

dispatch_semaphore_wait使對應的信號數(shù)量減1,如果執(zhí)行到這行代碼時信號數(shù)量已經(jīng)為0,那么在指定時間后才會去執(zhí)行它后面的代碼,指定時間為它的第二個參數(shù),如果設置為DISPATCH_TIME_FOREVER將一直等待。

dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);


? ? dispatch_queue_t queue = dispatch_queue_create("task", DISPATCH_QUEUE_CONCURRENT);

? ? dispatch_async(queue, ^{

? ? ? ? NSLog(@"1===task===%@", [NSThread currentThread]);


? ? ? ? dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3* NSEC_PER_SEC)), queue, ^{

? ? ? ? ? ? dispatch_semaphore_signal(semaphore);

? ? ? ? });

? ? });


? ? dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

? ? dispatch_async(queue, ^{

? ? ? ? NSLog(@"2===task===%@", [NSThread currentThread]);

? ? });

  上述代碼打印結果如下

  上面信號量代碼中一開始創(chuàng)建 ?semaphore 信號數(shù)就是0,所以?dispatch_semaphore_wait 后面的代碼要等到信號數(shù)不為0才會去執(zhí)行,在 task1 執(zhí)行完畢后用?dispatch_semaphore_signal 給信號數(shù)加1,所以 task2 代碼就被執(zhí)行了。

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

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

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