Dispatch.h
Semaphore.h //GCD信號資源量
dispatch_semaphore_t
是GCD中用來控制資源訪問量的。共有三個函數
dispatch_semaphore_t dispatch_semaphore_create(long value);//創建同時可用資源量。
long dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout); //設置可用資源超時時間
long dispatch_semaphore_signal(dispatch_semaphore_t dsema);//解除對信號資源量的限制
- 對dispatch_semaphore_t的理解可以是:*
- 利用
dispatch_semaphore_create
創建系統可以同時使用的資源數,意思也就是臨時對系統可用資源數添加一個限制。 -
dispatch_semaphore_wait
用這個函數設置一下對可用資源增加這個限制的時間。一般兩個值DISPATCH_TIME_NOW
和DISPATCH_TIME_FOREVER
,也可以理解為臨時降低系統可用資源的數量。 -
dispatch_semaphore_signal
發送一個信號解除對系統可用資源數量的限制。
總結一下:這三個函數有點像高速公路臨時收費站,第一個函數增加一個收費站,也就是增加幾個收費窗口,第二個函數也就是這個臨時收費站有多久有效期,第三個函數相當于收費站上級給收費站發送的撤銷通知。
代碼
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);//數字可以修改
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); //時間可以修改
你的需要被限制代碼
dispatch_semaphore_signal(semaphore);
Dispatch_time
兩個函數
dispatch_time_t
dispatch_time(dispatch_time_t when, int64_t delta);
dispatch_time_t
dispatch_walltime(const struct timespec *_Nullable when, int64_t delta);
第一個函數
第一個參數是從什么時間開始,一般直接傳 DISPATCH_TIME_NOW; 表示從現在開始
第二個參數表示具體的時間長度(不能直接傳 int 或 float), 可以寫成這種形式 (int64_t)3* NSEC_PER_SEC
#define NSEC_PER_SEC 1000000000ull 每秒有1000000000納秒
#define NSEC_PER_MSEC 1000000ull 每毫秒有1000000納秒
#define USEC_PER_SEC 1000000ull 每秒有1000000微秒
#define NSEC_PER_USEC 1000ull 每微秒有1000納秒
注意 delta 的單位是納秒!
1秒的寫作方式可以是 1* NSEC_PER_SEC; 1000* NSEC_PER_MSEC; USEC_PER_SEC* NSEC_PER_USEC
第二個函數
第一個參數是一個結構體, 創建的是一個絕對的時間點,比如 2016年10月10日8點30分30秒, 如果你不需要自某一個特定的時刻開始,可以傳 NUll,表示自動獲取當前時區的當前時間作為開始時刻, 第二參數意義同第一個函數
dispatch_time_t time = dispatch_walltime(NULL, 5* NSEC_PER_SEC);
。
兩個函數的不同
例如: 從現在開始,1小時之后是觸發某個事件
使用第一個函數創建的是一個相對的時間,第一個參數開始時間參考的是當前系統的時鐘,當 device 進入休眠之后,系統的時鐘也會進入休眠狀態, 第一個函數同樣被掛起; 假如 device 在第一個函數開始執行后10分鐘進入了休眠狀態,那么這個函數同時也會停止執行,當你再次喚醒 device 之后,該函數同時被喚醒,但是事件的觸發就變成了從喚醒 device 的時刻開始,1小時之后
而第二個函數則不同,他創建的是一個絕對的時間點,一旦創建就表示從這個時間點開始,1小時之后觸發事件,假如 device 休眠了10分鐘,當再次喚醒 device 的時候,計算時間間隔的時間起點還是 開始時就設置的那個時間點, 而不會受到 device 是否進入休眠影響
源引自CSDN博客頑兒去
Dispatch_block
QOS_CLASS_T 質量服務等級,簡單點就是優先級
DISPATCH_BLOCK_BARRIER
//提交并發隊列時作為一個柵欄代碼塊使用,直接調用代碼塊的時候,這個參數沒有任何作用DISPATCH_BLOCK_DETACHED
如果直接調用用這個flag創建的代碼塊,block代碼塊執行過程中將忽略調用線程之前給代碼塊添加的一些屬性。本代碼塊執行過程中和質量服務等級無關,和屬性無關和請求無關,如果這個代碼塊被提交到一個隊列,那么它的執行和隊列屬性有關。DISPATCH_BLOCK_ASSIGN_CURRENT
用這個flag創建的代碼塊將被獲得創建代碼塊時的上下文屬性,如果直接使用這個block,那么它創建時獲得的上下文屬性等將在調用它的線程中可以使用,如果在一個隊列中調用這個block,那么將會用提交時的上下文屬性替換創建時的上下文屬性。使用DISPATCH_BLOCK_NO_QOS_CLASS
和dispatch_block_create_with_qos_class()
方法指定的質量服務等級會優先級高于用這個flag指定的質量服務優先級DISPATCH_BLOCK_NO_QOS_CLASS
不指定質量服務優先級創建的block,直接使用這個block,這個block的質量服務優先級是由調用線程決定的,如果被提交到一個隊列,將用提交時的質量服務級別替換相關的block實例的默認行為。創建的block用在函數dispatch_block_create_with_qos_class()
中,這個flag將被忽略。DISPATCH_BLOCK_INHERIT_QOS_CLASS
隊列的質量服務優先級優先于block中用這個flag指定的優先級,本參數只有在隊列沒有指定質量服務優先級的時候才起作用,dispatch_block
提交到一個異步執行隊列的時候使用默認是使用這個flag的(如果不是用dispatch_block創建的block),如果隊列中指定DISPATCH_BLOCK_ENFORCE_QOS_CLASS
或者直接調用block,這個參數將不起作用。DISPATCH_BLOCK_ENFORCE_QOS_CLASS
block的質量服務優先級大于隊列指定的質量服務優先級,隊列中同步執行的block使用這個flag作為默認值,直接調用也是使用這個作為默認值。
dispatch_block_t
dispatch_block_create(dispatch_block_flags_t flags, dispatch_block_t block);
- 第一種創建block方式
用指定的flag值和block在堆區(copy的方式)創建一個新的block,新的block可以通過dispatch_async()調用或者直接調用,可以被調用任意次數,但是只有第一次能被dispatch_block_wait()等待和dispatch_block_notify()觀察
如果新創建的block被提交到一個隊列,除非block是用DISPATCH_BLOCK_ASSIGN_CURRENT,DISPATCH_BLOCK_NO_QOS_CLASS,DISPATCH_BLOCK_DETACHED創建的,否則它的質量服務優先級都由創建這個block時指定的flag決定。
新創建的block執行時的質量服務優先級同時取決于隊列的QOS 和 創建block時的flag,
dispatch_block_t excutBlock = dispatch_block_create(DISPATCH_BLOCK_BARRIER, ^{
NSLog(@"perform block with only one");
});
- 第二種創建block方式
直接調用的時候只要只要創建的時候的QOS不會導致調用線程的QOS變低就行。
如果新創建的block被提交到一個串行隊列并且被指定了QOS,系統將盡可能的用必要的qos覆蓋來確保這個提交到串行隊列的block在同等級的qos或者更高的qos等級執行。
qos傳QOS_CLASS_UNSPECIFIED和指定block的flag為DISPATCH_BLOCK_NO_QOS_CLASS效果一樣,傳其他值將導致返回的block為空。
relative_priority 是一個負的便宜量,如果指定一個大于0 小于QOS_MIN_RELATIVE_PRIORITY(一個宏定義值為-15)的值將導致創建出來的block為null
block 用來創建新block的原始block
dispatch_block_t testBlock = dispatch_block_create_with_qos_class(DISPATCH_BLOCK_NO_QOS_CLASS, QOS_CLASS_UNSPECIFIED, -10, ^{
NSLog(@"這是dispatch_block_create_with_qos_class創建的block");
});
testBlock(); //直接調用
同步阻塞線程,直到傳入的block執行完成或者時間過期(也就是傳入的時間參數過期了)
dispatch_block_wait(testBlock, DISPATCH_TIME_FOREVER);
給被執行的block添加一個通知block,當被執行的block執行完成之后會自動調用通知block
dispatch_block_notify(testBlock, dispatch_get_main_queue(), ^{
NSLog(@"notificationBlock");
});
只能取消還沒有執行的block,已經在執行的block不能被取消
dispatch_block_cancel(testBlock);