1. Dispatch Queue
執(zhí)行處理有兩種Dispatch Queue,。
一種是等待現(xiàn)在執(zhí)行中的處理的Serial Dispatch Queue,。(順序執(zhí)行)
另一種是不等待現(xiàn)在執(zhí)行中處理的Concurrent Dispatch Queue,。(并行執(zhí)行)
Concurrent Dispatch Queue執(zhí)行:
線程0 |
線程1 |
線程2 |
線程3 |
blk0 |
blk1 |
blk2 |
blk3 |
blk5 |
blk6 |
blk4 |
|
blk7 |
|
|
|
2. dispatch_queue_create
通過 dispatch_queue_create 函數(shù)可以生成 Dispathch Queue,。
- // 第一個參數(shù)為queue署名,。第二個參數(shù)為創(chuàng)建的queue類型。null默認為Serial dispatch queue
- dispatch_queue_t myDispatchQueue = dispatch_queue_create(“com.example.queue”, NULL);
-
- // dispatch_queue_t myDispatchQueue = dispatch_queue_create(“com.example.queue”, DIDPATCH_QUEUE_CONCURRENT);
-
- dispatch_async(myDispatchQueue, ^{ NSLog(@“ block on queue “); });
-
- // 結(jié)束后需要release
- dispatch_release(myDispatchQueue);
-
- // 相應(yīng)的有retain函數(shù)
- // dispatch_retain(myDispatchQueue);
雖然一執(zhí)行完 dispatch_async 后里面釋放queue,,但是由于Block持有該Dispatch Queue,,所以此處release后 queue 不會被廢棄。
3. Main Dispatch Queue 和 Global Dispatch Queue
以上兩種為系統(tǒng)標準提供的Dispatch Queue,;
名稱 |
Dispatch Queue種類 |
說明 |
Main Dispatch Queue |
Serial Dispatch Queue |
主線程執(zhí)行 |
DISPATCH_QUEUE_PRIORITY_HIGH |
Concurrent Dispatch Queue |
高優(yōu)先級 |
DISPATCH_QUEUE_PRIORITY_DEFAULT |
Concurrent Dispatch Queue |
默認優(yōu)先級 |
DISPATCH_QUEUE_PRIORITY_LOW |
Concurrent Dispatch Queue |
低優(yōu)先級 |
DISPATCH_QUEUE_PRIORITY_BACKGROUND |
Concurrent Dispatch Queue |
后臺執(zhí)行 |
- // 獲取主線程
- dispatch_queue_t mainDispatchQueue = dispatch_get_main_queue();
-
- //
- dispatch_queue_t globalDispatchQueueHigh = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
-
- //
- dispatch_queue_t globalDispatchQueueDefault = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
-
- //
- dispatch_queue_t globalDispatchQueueLow = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);
-
- //
- dispatch_queue_t globalDispatchQueueBackground = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
注:dispatch_retain() 和 dispatch_release() 對于這兩種queue不會引起任何變化,。
4. dispatch_set_target_queue
dispatch_queue_create() 函數(shù)生成的無論是Serial 還是 Concurrent ,都是默認優(yōu)先級,。
使用 dispatch_set_target_queue 可以變更優(yōu)先級,。
例如:
- dispatch_queue_t myDispatchQueue = dispatch_queue_create(“com.example.queue”, NULL);
- dispatch_queue_t globalDispatchQueueBackground = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
- dispatch_set_target_queue(myDispatchQueue, globalDispatchQueueBackground);
以上代碼將 myDispatchQueue 的優(yōu)先級變更為 后臺優(yōu)先級。
5. dispatch_after
想要在指定時間后執(zhí)行處理,,可使用 dispatch_after,。
例如:3秒后將指定的Block 追加奧 Main Dispatch Queue 中。
- dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 33ull * NSEC_PER_SEC);
- dispatch_after(time, dispatch_get_main_queue(), ^{ NSLog(@“waited at least three seconds.”); });
注: dispatch_after 函數(shù)并不是在指定時間后執(zhí)行處理,,而是在指定時間后追加處理到Dispatch Queue,。例如Main Dispatch Queue在主線程的RunLoop中執(zhí)行。所以在比如每隔1/60秒執(zhí)行的RunLoop,,Block最快在3秒后執(zhí)行,,最慢在 3+1/60秒后執(zhí)行。
6. Dispatch Group
如果想要在追加到多個Dispatch Queue中的多個處理全部結(jié)束后執(zhí)行結(jié)束處理,,,,可使用Dispatch Group。
例如:
- dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
- dispatch_group_t group = dispatch_group_create();
-
- dispatch_group_async(group, queue, ^{NSLog(@“bll0”);});
- dispatch_group_async(group, queue, ^{NSLog(@“bll1”);});
- dispatch_group_async(group, queue, ^{NSLog(@“bll2”);});
-
- dispatch_group_notify(group, dispatch_get_main_queue(), ^{ NSLog(@“done”); });
- dispatch_release(group);
其中可以使用 dispatch_group_wait函數(shù)僅等待全部處理執(zhí)行結(jié)束:
- dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
- dispatch_group_t group = dispatch_group_create();
-
- dispatch_group_async(group, queue, ^{NSLog(@“bll0”);});
- dispatch_group_async(group, queue, ^{NSLog(@“bll1”);});
- dispatch_group_async(group, queue, ^{NSLog(@“bll2”);});
-
- dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
- dispatch_release(group);
注:dispatch_group_wait 的返回值為0,,標識全部處理執(zhí)行結(jié)束,;
返回值不為0,表示經(jīng)過了指定時間,,屬于Dispatch Group 的某一個處理還在執(zhí)行中;
由于 DISPATCH_TIME_FOREVER 標識永久等待,,故而返回值恒為0,;
dispatch_group_wait 可能會造成當前線程停止,,直至所有處理執(zhí)行結(jié)束。
7. dispatch_barrier_async
在多個并行處理之間插入指定處理后再繼續(xù)多個并行處理,。
例如:
- dispatch_queue_t queue = dispatch_queue_create(“com.example.queue”, DISPATCH_QUEUE_CONCURRENT);
-
- dispatch_async(queue, blk0_for_reading);
- dispatch_async(queue, blk1_for_reading);
- dispatch_async(queue, blk2_for_reading);
- dispatch_async(queue, blk3_for_reading);
- dispatch_barrier_async(queue, blk_for_writing);
- dispatch_async(queue, blk4_for_reading);
- dispatch_async(queue, blk5_for_reading);
- dispatch_async(queue, blk6_for_reading);
- dispatch_async(queue, blk7_for_reading);
- dispatch_async(queue, blk8_for_reading);
-
- dispatch_release(queue);
使用 Concurrent Dispatch Queue 和 dispatch_barrier_async 可實現(xiàn)高效率的數(shù)據(jù)庫訪問和文件訪問,。
8. dispatch_apply
該函數(shù)按指定的次數(shù)將指定的Block追加到指定的Dispatch Queue中,并等待全部處理執(zhí)行結(jié)束,。
例如:
- dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
- dispatch_apply(5, queue, ^(size_t index){ NSLog(@“%zu”, index); });
- NSLog(@“done”);
- // 運行結(jié)果
- 4
- 1
- 0
- 3
- 2
- done
9. dispatch_suspend / dispatch_resume
當追加大量處理到Dispatch Queue時,,在追加處理的過程中,希望不執(zhí)行一追加的處理,,例如驗算結(jié)果被Block截獲時,,一些處理會對這個演算結(jié)果造成影響。
可使用以上兩個函數(shù)掛起和恢復queue,。
10. Dispatch Semaphore
該函數(shù)是比 dispatch_barrier_async() 更細粒度的排他控制,。
先看一下例子:
- dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
- NSMutableArray *array = [[NSMutableArray alloc] init];
- for(int i = 0; i< 100000; ++i)
- {
- dispatch_async(queue, ^{ [array addObject:[NSNumber numberWithInt:i]]; });
- }
以上代碼執(zhí)行后由內(nèi)存錯誤導致應(yīng)用異常結(jié)束的概率很高。
Dispatch Semaphore 是持有計數(shù)的信號,。當計數(shù)為0時,,表示等待;計數(shù)為1或者大于1時,,減去1而不等待,;
- // 生成函數(shù),計數(shù)初始值為1
- dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
-
- // 一直等待,直到Dispatch Semaphore 的計數(shù)值達到大于等于1,;
- long result = dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
- if (result == 0)
- {
- // 可執(zhí)行其他需要進行排他控制的處理
- }else{
- // 在達到指定時間為止待機
- }
修改后的例子:
- dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
- // 保證可訪問NSMutableArray 的線程同時只能有一個
- dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
-
- NSMutableArray *array = [[NSMutableArray alloc] init];
- for(int i = 0; i< 100000; ++i)
- {
- dispatch_async(queue, ^{
- dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
- [array addObject:[NSNumber numberWithInt:i]];
- });
- }
- dispatch_release(semaphore);
11. dispatch_once
dispatch_once 函數(shù)保證在應(yīng)用程序執(zhí)行中只執(zhí)行一次指定處理的API,;
例如:
- static int initialized = NO;
- if (initialized == NO)
- {
- //initialized
- initialized = YES;
- }
可轉(zhuǎn)變成:
- static dispatch_once_t pred;
- dispatch_once(&pred, ^{
- //initialized
- });
|