Dispatch(semaphore+block+time)

Dispatch.h

Semaphore.h //GCD信號資源量

dispatch_semaphore_t是GCD中用來控制資源訪問量的。共有三個函數(shù)

dispatch_semaphore_t  dispatch_semaphore_create(long value);//創(chuàng)建同時可用資源量。
long  dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout); //設(shè)置可用資源超時時間
long  dispatch_semaphore_signal(dispatch_semaphore_t dsema);//解除對信號資源量的限制
  • 對dispatch_semaphore_t的理解可以是:*
  1. 利用dispatch_semaphore_create創(chuàng)建系統(tǒng)可以同時使用的資源數(shù),意思也就是臨時對系統(tǒng)可用資源數(shù)添加一個限制。
  2. dispatch_semaphore_wait用這個函數(shù)設(shè)置一下對可用資源增加這個限制的時間。一般兩個值DISPATCH_TIME_NOWDISPATCH_TIME_FOREVER,也可以理解為臨時降低系統(tǒng)可用資源的數(shù)量。
  3. dispatch_semaphore_signal發(fā)送一個信號解除對系統(tǒng)可用資源數(shù)量的限制。

總結(jié)一下:這三個函數(shù)有點像高速公路臨時收費站,第一個函數(shù)增加一個收費站,也就是增加幾個收費窗口,第二個函數(shù)也就是這個臨時收費站有多久有效期,第三個函數(shù)相當(dāng)于收費站上級給收費站發(fā)送的撤銷通知。

代碼
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);//數(shù)字可以修改
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); //時間可以修改

你的需要被限制代碼

dispatch_semaphore_signal(semaphore);

Dispatch_time

兩個函數(shù)

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);
第一個函數(shù)

第一個參數(shù)是從什么時間開始,一般直接傳 DISPATCH_TIME_NOW; 表示從現(xiàn)在開始
第二個參數(shù)表示具體的時間長度(不能直接傳 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

第二個函數(shù)

第一個參數(shù)是一個結(jié)構(gòu)體, 創(chuàng)建的是一個絕對的時間點,比如 2016年10月10日8點30分30秒, 如果你不需要自某一個特定的時刻開始,可以傳 NUll,表示自動獲取當(dāng)前時區(qū)的當(dāng)前時間作為開始時刻, 第二參數(shù)意義同第一個函數(shù)
dispatch_time_t time = dispatch_walltime(NULL, 5* NSEC_PER_SEC);。
兩個函數(shù)的不同

例如: 從現(xiàn)在開始,1小時之后是觸發(fā)某個事件
使用第一個函數(shù)創(chuàng)建的是一個相對的時間,第一個參數(shù)開始時間參考的是當(dāng)前系統(tǒng)的時鐘,當(dāng) device 進入休眠之后,系統(tǒng)的時鐘也會進入休眠狀態(tài), 第一個函數(shù)同樣被掛起; 假如 device 在第一個函數(shù)開始執(zhí)行后10分鐘進入了休眠狀態(tài),那么這個函數(shù)同時也會停止執(zhí)行,當(dāng)你再次喚醒 device 之后,該函數(shù)同時被喚醒,但是事件的觸發(fā)就變成了從喚醒 device 的時刻開始,1小時之后
而第二個函數(shù)則不同,他創(chuàng)建的是一個絕對的時間點,一旦創(chuàng)建就表示從這個時間點開始,1小時之后觸發(fā)事件,假如 device 休眠了10分鐘,當(dāng)再次喚醒 device 的時候,計算時間間隔的時間起點還是 開始時就設(shè)置的那個時間點, 而不會受到 device 是否進入休眠影響

源引自CSDN博客頑兒去

Dispatch_block

QOS_CLASS_T 質(zhì)量服務(wù)等級,簡單點就是優(yōu)先級

  1. DISPATCH_BLOCK_BARRIER //提交并發(fā)隊列時作為一個柵欄代碼塊使用,直接調(diào)用代碼塊的時候,這個參數(shù)沒有任何作用
  2. DISPATCH_BLOCK_DETACHED 如果直接調(diào)用用這個flag創(chuàng)建的代碼塊,block代碼塊執(zhí)行過程中將忽略調(diào)用線程之前給代碼塊添加的一些屬性。本代碼塊執(zhí)行過程中和質(zhì)量服務(wù)等級無關(guān),和屬性無關(guān)和請求無關(guān),如果這個代碼塊被提交到一個隊列,那么它的執(zhí)行和隊列屬性有關(guān)。
  3. DISPATCH_BLOCK_ASSIGN_CURRENT 用這個flag創(chuàng)建的代碼塊將被獲得創(chuàng)建代碼塊時的上下文屬性,如果直接使用這個block,那么它創(chuàng)建時獲得的上下文屬性等將在調(diào)用它的線程中可以使用,如果在一個隊列中調(diào)用這個block,那么將會用提交時的上下文屬性替換創(chuàng)建時的上下文屬性。使用DISPATCH_BLOCK_NO_QOS_CLASSdispatch_block_create_with_qos_class()方法指定的質(zhì)量服務(wù)等級會優(yōu)先級高于用這個flag指定的質(zhì)量服務(wù)優(yōu)先級
  4. DISPATCH_BLOCK_NO_QOS_CLASS 不指定質(zhì)量服務(wù)優(yōu)先級創(chuàng)建的block,直接使用這個block,這個block的質(zhì)量服務(wù)優(yōu)先級是由調(diào)用線程決定的,如果被提交到一個隊列,將用提交時的質(zhì)量服務(wù)級別替換相關(guān)的block實例的默認(rèn)行為。創(chuàng)建的block用在函數(shù)dispatch_block_create_with_qos_class()中,這個flag將被忽略。
  5. DISPATCH_BLOCK_INHERIT_QOS_CLASS 隊列的質(zhì)量服務(wù)優(yōu)先級優(yōu)先于block中用這個flag指定的優(yōu)先級,本參數(shù)只有在隊列沒有指定質(zhì)量服務(wù)優(yōu)先級的時候才起作用,dispatch_block 提交到一個異步執(zhí)行隊列的時候使用默認(rèn)是使用這個flag的(如果不是用dispatch_block創(chuàng)建的block),如果隊列中指定DISPATCH_BLOCK_ENFORCE_QOS_CLASS或者直接調(diào)用block,這個參數(shù)將不起作用。
  6. DISPATCH_BLOCK_ENFORCE_QOS_CLASS block的質(zhì)量服務(wù)優(yōu)先級大于隊列指定的質(zhì)量服務(wù)優(yōu)先級,隊列中同步執(zhí)行的block使用這個flag作為默認(rèn)值,直接調(diào)用也是使用這個作為默認(rèn)值。
dispatch_block_t
dispatch_block_create(dispatch_block_flags_t flags, dispatch_block_t block);
  1. 第一種創(chuàng)建block方式
    用指定的flag值和block在堆區(qū)(copy的方式)創(chuàng)建一個新的block,新的block可以通過dispatch_async()調(diào)用或者直接調(diào)用,可以被調(diào)用任意次數(shù),但是只有第一次能被dispatch_block_wait()等待和dispatch_block_notify()觀察
    如果新創(chuàng)建的block被提交到一個隊列,除非block是用DISPATCH_BLOCK_ASSIGN_CURRENT,DISPATCH_BLOCK_NO_QOS_CLASS,DISPATCH_BLOCK_DETACHED創(chuàng)建的,否則它的質(zhì)量服務(wù)優(yōu)先級都由創(chuàng)建這個block時指定的flag決定。
    新創(chuàng)建的block執(zhí)行時的質(zhì)量服務(wù)優(yōu)先級同時取決于隊列的QOS 和 創(chuàng)建block時的flag,
dispatch_block_t   excutBlock = dispatch_block_create(DISPATCH_BLOCK_BARRIER, ^{
        NSLog(@"perform block  with  only one");
    });
  1. 第二種創(chuàng)建block方式

直接調(diào)用的時候只要只要創(chuàng)建的時候的QOS不會導(dǎo)致調(diào)用線程的QOS變低就行。
如果新創(chuàng)建的block被提交到一個串行隊列并且被指定了QOS,系統(tǒng)將盡可能的用必要的qos覆蓋來確保這個提交到串行隊列的block在同等級的qos或者更高的qos等級執(zhí)行。
qos傳QOS_CLASS_UNSPECIFIED和指定block的flag為DISPATCH_BLOCK_NO_QOS_CLASS效果一樣,傳其他值將導(dǎo)致返回的block為空。
relative_priority 是一個負(fù)的便宜量,如果指定一個大于0 小于QOS_MIN_RELATIVE_PRIORITY(一個宏定義值為-15)的值將導(dǎo)致創(chuàng)建出來的block為null
block 用來創(chuàng)建新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創(chuàng)建的block");
  });
  testBlock(); //直接調(diào)用

同步阻塞線程,直到傳入的block執(zhí)行完成或者時間過期(也就是傳入的時間參數(shù)過期了)

dispatch_block_wait(testBlock, DISPATCH_TIME_FOREVER);

給被執(zhí)行的block添加一個通知block,當(dāng)被執(zhí)行的block執(zhí)行完成之后會自動調(diào)用通知block

dispatch_block_notify(testBlock, dispatch_get_main_queue(), ^{
        NSLog(@"notificationBlock");
    });

只能取消還沒有執(zhí)行的block,已經(jīng)在執(zhí)行的block不能被取消

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

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

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