dispatch queue.h

版本:iOS13.5

queue.h

dispatch其他文件通道

同步和異步的區(qū)別
當(dāng)運行到dispatch_async時测摔,會立即返回托呕,繼續(xù)執(zhí)行下面的代碼,而block會在隊列queue中排隊,輪到自己后執(zhí)行景描。
當(dāng)運行到dispatch_sync時,會先讓block在隊列queue中排隊秀撇,輪到自己后執(zhí)行超棺,blcok里代碼執(zhí)行完畢后,才會返回呵燕,再繼續(xù)執(zhí)行下面的代碼棠绘。
串行和并行的區(qū)別
串行時,block會在隊列queue中排隊再扭,輪到自己后在隊列queue開的線程(只有一個)中執(zhí)行氧苍,若block是同步的,會先執(zhí)行完block中的代碼泛范,再執(zhí)行下一個block让虐。若block是異步的,不管blcok中代碼是否執(zhí)行完罢荡,會繼續(xù)執(zhí)行下一個block赡突。
并行時,block會在隊列queue中排隊柠傍,然后隊列queue會為每一個block開一個線程麸俘,每一個block會在自己所屬的線程中執(zhí)行。

索引

  • 提交回調(diào)block到調(diào)度隊列queue上并異步執(zhí)行
    dispatch_async
  • 提交函數(shù)work到調(diào)度隊列queue上并異步執(zhí)行
    dispatch_async_f
  • 提交回調(diào)block到調(diào)度隊列queue上并同步執(zhí)行
    dispatch_sync
  • 提交函數(shù)work到調(diào)度隊列queue上并同步執(zhí)行
    dispatch_sync_f
  • 提交回調(diào)block到調(diào)度隊列queue上并同步執(zhí)行(會先等待queue中的異步block執(zhí)行完成)
    dispatch_async_and_wait
  • 提交函數(shù)work到調(diào)度隊列queue上并同步執(zhí)行(會先等待queue中的異步block執(zhí)行完成)
    dispatch_async_and_wait_f
  • 提交回調(diào)block到調(diào)度隊列queue上并且并行調(diào)用惧笛。
    dispatch_apply
  • 提交函數(shù)work到調(diào)度隊列queue上并且并行調(diào)用从媚。
    dispatch_apply_f
  • 返回綁定到主線程的默認(rèn)隊列。
    dispatch_get_main_queue
  • 創(chuàng)建一個全局并發(fā)隊列患整。
    dispatch_get_global_queue
  • 將調(diào)度隊列屬性值變成初始不活躍的屬性值
    dispatch_queue_attr_make_initially_inactive
  • 為調(diào)度隊列屬性值設(shè)置自動釋放頻率frequency
    dispatch_queue_attr_make_with_autorelease_frequency
  • 為調(diào)度隊列屬性值設(shè)置QOS類qos_class和相對優(yōu)先級relative_priority
    dispatch_queue_attr_make_with_qos_class
  • 創(chuàng)建一個新的調(diào)度隊列
    dispatch_queue_create
  • 根據(jù)目標(biāo)隊列target創(chuàng)建一個新的調(diào)度隊列拜效。
    dispatch_queue_create_with_target
  • 返回隊列的標(biāo)簽
    dispatch_queue_get_label
  • 返回隊列的qos類和相對優(yōu)先級
    dispatch_queue_get_qos_class
  • 為對象object設(shè)置目標(biāo)隊列喷众。
    dispatch_set_target_queue
  • 執(zhí)行提交到主隊列的block(不要調(diào)用)
    dispatch_main
  • 安排一個block在指定時間when并在隊列queue上執(zhí)行
    dispatch_after
  • 安排一個函數(shù)work在指定時間when并在隊列queue上執(zhí)行。
    dispatch_after_f
  • 提交屏障block到調(diào)度隊列queue上并異步執(zhí)行紧憾。
    dispatch_barrier_async
  • 提交屏障函數(shù)work到調(diào)度隊列queue上并異步執(zhí)行到千。
    dispatch_barrier_async_f
  • 提交屏障block到調(diào)度隊列queue上并同步執(zhí)行。
    dispatch_barrier_sync
  • 提交屏障函數(shù)work到調(diào)度隊列queue上并同步執(zhí)行赴穗。
    dispatch_barrier_sync_f
  • 提交屏障block到調(diào)度隊列queue上并同步執(zhí)行憔四。(會先等待queue中的異步項執(zhí)行完成)
    dispatch_barrier_async_and_wait
  • 提交屏障函數(shù)work到調(diào)度隊列queue上并同步執(zhí)行。(會先等待queue中的異步項執(zhí)行完成)
    dispatch_barrier_async_and_wait_f
  • 給調(diào)度隊列queue設(shè)置對應(yīng)鍵值key的上下文context般眉。
    dispatch_queue_set_specific
  • 通過鍵值key獲取調(diào)度隊列queue的上下文context了赵。
    dispatch_queue_get_specific
  • 通過對應(yīng)鍵值key獲取當(dāng)前隊列的上下文context。
    dispatch_get_specific
  • 驗證當(dāng)前的block是否在調(diào)度隊列queue上執(zhí)行甸赃。
    dispatch_assert_queue
  • 驗證當(dāng)前的block是否在調(diào)度隊列queue上執(zhí)行柿汛,并且將block充當(dāng)隊列queue上的屏障block。
    dispatch_assert_queue_barrier
  • 驗證當(dāng)前的block是否不在調(diào)度隊列queue上執(zhí)行埠对。
    dispatch_assert_queue_not

詳解

  • 提交回調(diào)block到調(diào)度隊列queue上并異步執(zhí)行
void dispatch_async(dispatch_queue_t queue, dispatch_block_t block);

queue 要提交到的隊列络断。系統(tǒng)將在隊列上保留引用,直到block完成為止项玛。
block 提交給隊列的塊

  • 提交函數(shù)work到調(diào)度隊列queue上并異步執(zhí)行
void dispatch_async_f(dispatch_queue_t queue,
        void *_Nullable context, dispatch_function_t work);

work 函數(shù)typedef void (*dispatch_function_t)(void *_Nullable);
context 函數(shù)work要傳入的參數(shù) 是一個任意值的指針

例:
    dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);
    dispatch_async(queue, ^{
        NSLog(@"block");
    });
    int num = 2;
    dispatch_async_f(queue, &num, work);

void work(void *context) {
    NSLog(@"work");
}
輸出:異步執(zhí)行 順序不定
block
work
或
work
block
  • 提交回調(diào)block到調(diào)度隊列queue上并同步執(zhí)行
void dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);

提交到隊列的block在調(diào)用時不會遵守該隊列的某些隊列屬性(例如自動釋放頻率dispatch_queue_attr_make_with_autorelease_frequency和QOS類qos_class_t)貌笨。
應(yīng)注意死鎖的問題。
參數(shù)說明見dispatch_async

  • 提交函數(shù)work到調(diào)度隊列queue上并同步執(zhí)行
void dispatch_sync_f(dispatch_queue_t queue, 
            void *_Nullable context, dispatch_function_t work);

參數(shù)說明見dispatch_async_f

例:
    dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);
    dispatch_async(dispatch_get_main_queue(), ^{
        dispatch_sync(queue, ^{
            NSLog(@"sync_blcok");
            [NSThread sleepForTimeInterval:2];
        });
        dispatch_sync_f(queue, NULL, work);
    });

void work(void *context) {
    NSLog(@"work");
}
輸出:
09:50:15.197956+0800 DEMO[43747:11194017] sync_blcok
09:50:17.199334+0800 DEMO[43747:11194017] work
  • 提交回調(diào)block到調(diào)度隊列queue上并同步執(zhí)行(會先等待queue中的異步block執(zhí)行完成)
void dispatch_async_and_wait(dispatch_queue_t queue, dispatch_block_t block);

也會出現(xiàn)死鎖的情況
dispatch_sync的不同點
提交到隊列的block在調(diào)用時會遵守該隊列的所有隊列屬性(例如自動釋放頻率和QOS類)稍计。
當(dāng)運行時調(diào)出一個線程來調(diào)用已經(jīng)提交給隊列的異步block時躁绸,該服務(wù)線程也將用于執(zhí)行通過dispatch_async_and_wait提交給隊列的同步block。
如果運行時沒有該服務(wù)線程(因為它沒有排隊的block臣嚣,或者只有同步block),則dispatch_async_and_wait將與dispatch_sync功能一致

例1:
    dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);
    dispatch_async(dispatch_get_main_queue(), ^{
        if (@available(iOS 12.0, *)) {
            dispatch_async_and_wait(queue, ^{
                NSLog(@"wait1");
                [NSThread sleepForTimeInterval:2];
            });
            dispatch_async_and_wait(queue, ^{
                NSLog(@"wait2");
            });
        }
    });
輸出:由于queue中沒有異步工作項 所以效果與dispatch_sync一致
10:14:03.208297+0800 DEMO[44127:11218481] wait1
10:14:05.208632+0800 DEMO[44127:11218481] wait2
例2:
    dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);
    dispatch_async(dispatch_get_main_queue(), ^{
        if (@available(iOS 12.0, *)) {
            dispatch_async_and_wait(queue, ^{
                NSLog(@"wait1");
                [NSThread sleepForTimeInterval:2];
            });
            dispatch_async_and_wait(queue, ^{
                NSLog(@"wait2");
            });
        }
    });
    dispatch_async(queue, ^{
        NSLog(@"async1");
        [NSThread sleepForTimeInterval:1];
    });
    dispatch_async(queue, ^{
        NSLog(@"async2");
        [NSThread sleepForTimeInterval:2];
    });
輸出:queue中有異步工作項剥哑,所以會先等兩個async執(zhí)行完后 才會執(zhí)行dispatch_async_and_wait
10:17:07.668667+0800 DEMO[44169:11221766] async1
10:17:08.671300+0800 DEMO[44169:11221766] async2
10:17:10.672588+0800 DEMO[44169:11221766] wait1
10:17:12.673911+0800 DEMO[44169:11221347] wait2
  • 提交函數(shù)work到調(diào)度隊列queue上并同步執(zhí)行(會先等待queue中的異步block執(zhí)行完成)
void dispatch_async_and_wait_f(dispatch_queue_t queue,
        void *_Nullable context, dispatch_function_t work);

參數(shù)說明見dispatch_async_f

  • 提交回調(diào)block到調(diào)度隊列queue上并且并行調(diào)用硅则。
void dispatch_apply(size_t iterations, dispatch_queue_t queue, void (^block)(size_t));

該方法在返回之前等待全部block執(zhí)行完成。如果隊列是并發(fā)的株婴,則可以同時調(diào)用block怎虫。
iterations 要執(zhí)行的迭代次數(shù)
queue block要提交到的調(diào)度隊列。傳遞的首選值是DISPATCH_APPLY_AUTO困介,以自動使用適合于調(diào)用線程的隊列大审。
block void (^block)(size_t) 其中的size_t是當(dāng)前迭代的索引

例1:
    dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);
    dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"apply start");
        dispatch_apply(3, queue, ^(size_t index) {
            NSLog(@"start %ld", index);
            [NSThread sleepForTimeInterval:index+1];
            NSLog(@"end %ld", index);
        });
        NSLog(@"apply end");
    });
輸出:因為queue是串行隊列,所有每個block之間是排隊串行執(zhí)行的取刃,并且全部block執(zhí)行完成后衩辟,才會繼續(xù)執(zhí)行下面的代碼汰规。
10:39:19.035150+0800 DEMO[44455:11241456] apply start
10:39:19.035257+0800 DEMO[44455:11241456] start 0
10:39:20.035390+0800 DEMO[44455:11241456] end 0
10:39:20.035589+0800 DEMO[44455:11241456] start 1
10:39:22.035951+0800 DEMO[44455:11241456] end 1
10:39:22.036224+0800 DEMO[44455:11241456] start 2
10:39:25.037368+0800 DEMO[44455:11241456] end 2
10:39:25.037586+0800 DEMO[44455:11241456] apply end
例2:
將queue改成DISPATCH_APPLY_AUTO
輸出:因為DISPATCH_APPLY_AUTO分配了一個并行隊列,各個Block之間是并行執(zhí)行的姜骡,待全部block執(zhí)行完成后导坟,才會繼續(xù)執(zhí)行下面的代碼
10:46:27.792156+0800 DEMO[44525:11246686] apply start
10:46:27.792270+0800 DEMO[44525:11246686] start 0
10:46:27.792284+0800 DEMO[44525:11247284] start 1
10:46:27.792285+0800 DEMO[44525:11247279] start 2
10:46:28.793504+0800 DEMO[44525:11246686] end 0
10:46:29.792435+0800 DEMO[44525:11247284] end 1
10:46:30.793337+0800 DEMO[44525:11247279] end 2
10:46:30.793585+0800 DEMO[44525:11246686] apply end
  • 提交函數(shù)work到調(diào)度隊列queue上并且并行調(diào)用。
void dispatch_apply_f(size_t iterations, dispatch_queue_t queue,
        void *_Nullable context, void (*work)(void *_Nullable, size_t));

work參數(shù)詳情見dispatch_async_f

  • 返回綁定到主線程的默認(rèn)隊列圈澈。
dispatch_queue_main_t dispatch_get_main_queue(void)惫周;

主隊列是綁定到應(yīng)用程序主線程的串行隊列。主隊列是無法修改的康栈,在主隊列上調(diào)用dispatch_suspend递递、dispatch_resumedispatch_set_context等將無效啥么。
因為主隊列的行為并不完全像常規(guī)的串行隊列漾狼,所以在非UI應(yīng)用程序(守護程序)的進程中使用時,主隊列可能會產(chǎn)生有害的副作用饥臂。對于此類過程逊躁,應(yīng)避免使用主隊列。

  • 創(chuàng)建一個全局并發(fā)隊列隅熙。
dispatch_queue_global_t dispatch_get_global_queue(long identifier, unsigned long flags);

全局并發(fā)隊列在系統(tǒng)管理的線程池之上提供了優(yōu)先級存儲桶稽煤。系統(tǒng)將根據(jù)需求和系統(tǒng)負(fù)載來決定向該池分配多少個線程。特別是囚戚,系統(tǒng)嘗試為此資源維護良好的并發(fā)級別酵熙,并且當(dāng)太多現(xiàn)有工作線程在系統(tǒng)調(diào)用中阻塞時,系統(tǒng)將創(chuàng)建新線程驰坊。
全局并發(fā)隊列是共享資源匾二,因此,此資源的每個用戶都有責(zé)任不向該池提交無限數(shù)量的工作拳芙,尤其是可能阻塞的工作察藐,因為這可能導(dǎo)致系統(tǒng)產(chǎn)生非常大的數(shù)量線程數(shù)(又名線程爆炸)。
提交到全局并發(fā)隊列的工作項是沒有順序保證的舟扎,并且工作項可以同時調(diào)用分飞。
全局并發(fā)隊列是無法修改的,在隊列上調(diào)用dispatch_suspend睹限、dispatch_resume譬猫、dispatch_set_context等將無效。

identifier qos_class_t表示服務(wù)質(zhì)量等級 dispatch_queue_priority_t表示優(yōu)先級羡疗。
qos_class_t 詳細(xì)可查看dispatch block.hdispatch_block_create_with_qos_class方法
dispatch_queue_priority_t 優(yōu)先級從上往下逐漸變低

//項目將以高優(yōu)先級運行染服,即,將在任何默認(rèn)優(yōu)先級或低優(yōu)先級隊列之前執(zhí)行叨恨。
#define DISPATCH_QUEUE_PRIORITY_HIGH 2
//項目將以默認(rèn)優(yōu)先級運行
#define DISPATCH_QUEUE_PRIORITY_DEFAULT 0
//調(diào)度到隊列的項目將以低優(yōu)先級運行
#define DISPATCH_QUEUE_PRIORITY_LOW (-2)
//調(diào)度到隊列的項目將在后臺優(yōu)先級下運行
#define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN
typedef long dispatch_queue_priority_t;

flags 保留以備將來使用柳刮。傳遞除0以外的任何值可能會導(dǎo)致返回NULL。

  • 將調(diào)度隊列屬性值變成初始不活躍的屬性值
dispatch_queue_attr_t dispatch_queue_attr_make_initially_inactive(
        dispatch_queue_attr_t _Nullable attr);

調(diào)用dispatch_queue_create時傳入不活躍的屬性值時能使創(chuàng)建的隊列初始不活躍,之后可以通過dispatch_activatedispatch_resume激活诚亚。
可以使用dispatch_set_target_queue更改處于不活躍隊列的目標(biāo)隊列晕换。一旦初始不活躍隊列被激活,就不再允許更改目標(biāo)隊列站宗。
必須先激活才能釋放不活躍的隊列闸准。
attr 活躍的屬性值

//用于創(chuàng)建調(diào)度隊列的屬性,該調(diào)度隊列按FIFO順序串行調(diào)用block梢灭。
#define DISPATCH_QUEUE_SERIAL NULL
//與DISPATCH_QUEUE_SERIAL相同夷家,但是它是初始不活躍的。
#define DISPATCH_QUEUE_SERIAL_INACTIVE \
dispatch_queue_attr_make_initially_inactive(DISPATCH_QUEUE_SERIAL)
//用于創(chuàng)建調(diào)度隊列的屬性敏释,該調(diào)度隊列可同時調(diào)用block并使用提交給調(diào)度屏障API的屏障blcok
#define DISPATCH_QUEUE_CONCURRENT \
        DISPATCH_GLOBAL_OBJECT(dispatch_queue_attr_t, \
        _dispatch_queue_attr_concurrent)
//與DISPATCH_QUEUE_CONCURRENT相同库快,但是它是初始不活躍的。
#define DISPATCH_QUEUE_CONCURRENT_INACTIVE \
dispatch_queue_attr_make_initially_inactive(DISPATCH_QUEUE_CONCURRENT)

如上所示
DISPATCH_QUEUE_SERIAL_INACTIVE = dispatch_queue_attr_make_initially_inactive(DISPATCH_QUEUE_SERIAL)
DISPATCH_QUEUE_CONCURRENT_INACTIVE = dispatch_queue_attr_make_initially_inactive(DISPATCH_QUEUE_CONCURRENT)

  • 為調(diào)度隊列屬性值設(shè)置自動釋放頻率frequency
dispatch_queue_attr_t dispatch_queue_attr_make_with_autorelease_frequency(
        dispatch_queue_attr_t _Nullable attr, dispatch_autorelease_frequency_t frequency);

設(shè)置自動釋放頻率對同步提交到隊列(dispatch_sync钥顽、dispatch_barrier_sync)的block沒有影響义屏。
dispatch_get_global_queue創(chuàng)建的全局并發(fā)隊列具有DISPATCH_AUTORELEASE_FREQUENCY_NEVER行為。
dispatch_queue_create手動創(chuàng)建的調(diào)度隊列默認(rèn)情況下使用DISPATCH_AUTORELEASE_FREQUENCY_INHERIT蜂大。

frequency 自動釋放頻率

DISPATCH_ENUM(dispatch_autorelease_frequency, unsigned long,
//具有此自動釋放頻率的調(diào)度隊列將從其目標(biāo)隊列繼承全部行為闽铐。這是手動創(chuàng)建的隊列的默認(rèn)值。
    DISPATCH_AUTORELEASE_FREQUENCY_INHERIT  = 0,
//具有這種自動釋放頻率的調(diào)度隊列會推送并彈出一個自動釋放池去異步執(zhí)行提交給它的每一個block
    DISPATCH_AUTORELEASE_FREQUENCY_WORK_ITEM  = 1,
//具有這種自動釋放頻率的調(diào)度隊列永遠不會設(shè)置單個自動釋放池去異步執(zhí)行提交給它的block奶浦,這是全局并發(fā)隊列的默認(rèn)值兄墅。
    DISPATCH_AUTORELEASE_FREQUENCY_NEVER  = 2,
);
  • 為調(diào)度隊列屬性值設(shè)置QOS類qos_class和相對優(yōu)先級relative_priority
dispatch_queue_attr_t
dispatch_queue_attr_make_with_qos_class(dispatch_queue_attr_t _Nullable attr,
        dispatch_qos_class_t qos_class, int relative_priority);

當(dāng)以這種方式設(shè)置時,QOS類和相對優(yōu)先級優(yōu)先于從調(diào)度隊列的目標(biāo)隊列dispatch_set_target_queue繼承的優(yōu)先級
qos_class 詳情見dispatch_get_global_queue
relative_priority QOS類中的相對優(yōu)先級澳叉。該值是與最大支持的調(diào)度程序優(yōu)先級的負(fù)偏移量隙咸。傳遞大于0或小于QOS_MIN_RELATIVE_PRIORITY的值將導(dǎo)致返回NULL。
#define QOS_MIN_RELATIVE_PRIORITY (-15)

例:
    //將DISPATCH_QUEUE_SERIAL變成非活躍的DISPATCH_QUEUE_SERIAL_INACTIVE
    dispatch_queue_attr_t attr = dispatch_queue_attr_make_initially_inactive(DISPATCH_QUEUE_SERIAL);
    //設(shè)置頻率
    attr = dispatch_queue_attr_make_with_autorelease_frequency(attr, DISPATCH_AUTORELEASE_FREQUENCY_INHERIT);
    //設(shè)置qos類
    attr = dispatch_queue_attr_make_with_qos_class(attr, QOS_CLASS_DEFAULT, 0);
    //創(chuàng)建串行隊列
    dispatch_queue_t attr_queue = dispatch_queue_create("attr_queue", attr);
    //激活隊列 因為DISPATCH_QUEUE_SERIAL_INACTIVE是不活躍的
    dispatch_activate(attr_queue);
  • 創(chuàng)建一個新的調(diào)度隊列
dispatch_queue_t dispatch_queue_create(const char *_Nullable label,
        dispatch_queue_attr_t _Nullable attr);

label 附加到隊列的字符串成洗。此參數(shù)可以為NULL五督。
attr 屬性值 DISPATCH_QUEUE_SERIAL串行 DISPATCH_QUEUE_CONCURRENT并行
可以通過dispatch_queue_attr_make_initially_inactive設(shè)置隊列的活躍狀態(tài)
可以通過dispatch_queue_attr_make_with_autorelease_frequency設(shè)置隊列的自動釋放頻率
可以通過dispatch_queue_attr_make_with_qos_class設(shè)置隊列的qos類和相對優(yōu)先級

  • 根據(jù)目標(biāo)隊列target創(chuàng)建一個新的調(diào)度隊列。
dispatch_queue_t dispatch_queue_create_with_target(const char *_Nullable label,
        dispatch_queue_attr_t _Nullable attr, dispatch_queue_t _Nullable target);

此方式創(chuàng)建的隊列不能更改其目標(biāo)隊列dispatch_set_target_queue泌枪,除非創(chuàng)建的隊列處于非活動狀態(tài)概荷,才可以更改目標(biāo)隊列,直到使用dispatch_activate激活為止碌燕。
target 目標(biāo)隊列 目標(biāo)隊列會被保留。如果此參數(shù)是DISPATCH_TARGET_QUEUE_DEFAULT继薛,則將隊列的目標(biāo)隊列設(shè)置為指定隊列類型的默認(rèn)目標(biāo)隊列修壕。
#define DISPATCH_TARGET_QUEUE_DEFAULT NULL

例:
    dispatch_queue_t queue1 = dispatch_queue_create("queue1", DISPATCH_QUEUE_SERIAL);
    dispatch_queue_t queue2 = dispatch_queue_create_with_target("queue2", DISPATCH_QUEUE_CONCURRENT, queue1);
    dispatch_queue_t queue3 = dispatch_queue_create_with_target("queue3", DISPATCH_QUEUE_SERIAL, DISPATCH_TARGET_QUEUE_DEFAULT);
  • 返回隊列的標(biāo)簽
const char * dispatch_queue_get_label(dispatch_queue_t _Nullable queue);

若創(chuàng)建時為標(biāo)簽為NULL,則返回空字符串遏考。
queue 隊列 若為DISPATCH_CURRENT_QUEUE_LABEL將返回當(dāng)前隊列的標(biāo)簽
#define DISPATCH_CURRENT_QUEUE_LABEL NULL

  • 返回隊列的qos類和相對優(yōu)先級
dispatch_qos_class_t dispatch_queue_get_qos_class(dispatch_queue_t queue,
        int *_Nullable relative_priority_ptr);

relative_priority_ptr 相對優(yōu)先級的指針
如果隊列是dispatch_queue_attr_make_with_qos_class返回的屬性值創(chuàng)建的慈鸠,則此函數(shù)返回的QOS類和相對優(yōu)先級;否則它將返回QOS_CLASS_UNSPECIFIED的QOS類和相對優(yōu)先級0灌具。
如果隊列是全局并發(fā)隊列青团,則此函數(shù)返回在dispatch_get_global_queue下記錄的已分配QOS類和相對優(yōu)先級0譬巫;否則,返回0督笆。
如果隊列是主隊列dispatch_get_main_queue芦昔,它將返回由qos_class_main提供的QOS值和相對優(yōu)先級0。

例:
    dispatch_queue_attr_t attr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, 0);
    dispatch_queue_t attr_queue = dispatch_queue_create("attr_queue", attr);
    const char *name = dispatch_queue_get_label(attr_queue);
    int priority = -10;
    dispatch_qos_class_t qos = dispatch_queue_get_qos_class(attr_queue, &priority);
    NSLog(@"%s %u %d", name, qos, priority);
輸出:
attr_queue 21 0
  • 為對象object設(shè)置目標(biāo)隊列娃肿。
void dispatch_set_target_queue(dispatch_object_t object,dispatch_queue_t _Nullable queue);

如果object在創(chuàng)建時沒有設(shè)置某些屬性(服務(wù)質(zhì)量等級和相對優(yōu)先級等)咕缎,則object將從其目標(biāo)隊列queue繼承這些屬性。
通常料扰,更改object的目標(biāo)隊列是異步操作凭豪,該操作不會立即生效,也不會影響已經(jīng)與object關(guān)聯(lián)的block晒杈。
但是嫂伞,如果在調(diào)用該方法時object處于非活動狀態(tài),則目標(biāo)隊列queue更改將立即生效拯钻,并將影響已經(jīng)與object關(guān)聯(lián)的block帖努。
設(shè)置目標(biāo)隊列后object的block將會被目標(biāo)隊列管理
object 對象 dispatch_queue_tdispatch_source_t都可以當(dāng)做dispatch_object_t使用
queue 對象object的新目標(biāo)隊列。會保留隊列说庭,并釋放先前的目標(biāo)隊列(如果有)然磷。如果queue是DISPATCH_TARGET_QUEUE_DEFAULT,則將為對象object設(shè)置指定對象類型的默認(rèn)目標(biāo)隊列刊驴。

例:
    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_CONCURRENT);
    
//    dispatch_queue_t queue4 = dispatch_queue_create("queue4", DISPATCH_QUEUE_SERIAL);
//    dispatch_set_target_queue(queue1, queue4);
//    dispatch_set_target_queue(queue2, queue4);
//    dispatch_set_target_queue(queue3, queue4);

    dispatch_async(queue1, ^{
        NSLog(@"queue1");
    });
    dispatch_async(queue2, ^{
        NSLog(@"queue2");
    });
    dispatch_async(queue3, ^{
        NSLog(@"queue3_1 start");
        [NSThread sleepForTimeInterval:2];
        NSLog(@"queue3_1 end");
    });
    dispatch_async(queue3, ^{
        NSLog(@"queue3_2 start");
        [NSThread sleepForTimeInterval:1];
        NSLog(@"queue3_2 end");
    });
輸出:queue1 queue2 queue3_1 start queue3_2 start這4項是同時亂序輸出的姿搜,1秒后輸出queue3_2 end 再1秒后輸出queue3_1 end 
16:31:25.040349+0800 DEMO[47673:11436311] queue3_2 start
16:31:25.040351+0800 DEMO[47673:11436310] queue2
16:31:25.040352+0800 DEMO[47673:11436322] queue3_1 start
16:31:25.040348+0800 DEMO[47673:11436316] queue1
16:31:26.044913+0800 DEMO[47673:11436311] queue3_2 end
16:31:27.045366+0800 DEMO[47673:11436322] queue3_1 end
若取消上面的注釋
則輸出: 可以看出所有異步執(zhí)行都變成了串行執(zhí)行,即使queue3是并發(fā)的捆憎,也變成了串行執(zhí)行舅柜,是因為所有的隊列都被queue4重新管理了,而queue4是串行的躲惰。
16:34:11.166613+0800 DEMO[47708:11438765] queue1
16:34:11.166768+0800 DEMO[47708:11438765] queue2
16:34:11.166896+0800 DEMO[47708:11438765] queue3_1 start
16:34:13.170399+0800 DEMO[47708:11438765] queue3_1 end
16:34:13.170603+0800 DEMO[47708:11438765] queue3_2 start
16:34:14.174332+0800 DEMO[47708:11438765] queue3_2 end
  • 執(zhí)行提交到主隊列的block(不要調(diào)用)
void dispatch_main(void);

此方法“駐留”主線程致份,并等待block提交到主隊列。
該函數(shù)永不返回础拨,所以不要調(diào)用氮块,不然會一直堵塞當(dāng)前線程。

  • 安排一個block在指定時間when并在隊列queue上執(zhí)行诡宗。
void dispatch_after(dispatch_time_t when, dispatch_queue_t queue,
                dispatch_block_t block);

when 傳入DISPATCH_TIME_NOW表示立即執(zhí)行 傳入DISPATCH_TIME_FOREVER表示永不執(zhí)行
傳入dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC)表示延時1秒鐘執(zhí)行

  • 安排一個函數(shù)work在指定時間when并在隊列queue上執(zhí)行滔蝉。
void dispatch_after_f(dispatch_time_t when, dispatch_queue_t queue,
        void *_Nullable context, dispatch_function_t work);

work 參數(shù)說明見dispatch_async_f

例:
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        //1秒鐘后執(zhí)行block
    });
  • 提交屏障block到調(diào)度隊列queue上并異步執(zhí)行。
void dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t block);

屏障塊僅在??使用DISPATCH_QUEUE_CONCURRENT屬性創(chuàng)建的隊列時才有特殊的效果塔沃;在這樣的隊列上蝠引,屏障block將不會運行,直到所有較早提交給隊列的block都已完成;屏障block之后提交給隊列的block也都不會運行螃概,直到屏障block完成矫夯。
當(dāng)提交到全局隊列dispatch_get_global_queue或未使用DISPATCH_QUEUE_CONCURRENT屬性創(chuàng)建的隊列時,該方法作用與dispatch_async吊洼、dispatch_sync相同训貌。

  • 提交屏障函數(shù)work到調(diào)度隊列queue上并異步執(zhí)行。
void dispatch_barrier_async_f(dispatch_queue_t queue,
        void *_Nullable context, dispatch_function_t work);

work 參數(shù)說明見dispatch_async_f

  • 提交屏障block到調(diào)度隊列queue上并同步執(zhí)行融蹂。
void dispatch_barrier_sync(dispatch_queue_t queue, dispatch_block_t block);
  • 提交屏障函數(shù)work到調(diào)度隊列queue上并同步執(zhí)行旺订。
void dispatch_barrier_sync_f(dispatch_queue_t queue, void *_Nullable context, 
                      dispatch_function_t work);

work 參數(shù)說明見dispatch_async_f

例:
    dispatch_queue_t queue1 = dispatch_queue_create("queue1", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue1, ^{
        NSLog(@"1");
    });
    dispatch_async(queue1, ^{
        NSLog(@"2");
    });
    dispatch_async(queue1, ^{
        NSLog(@"3");
    });
    dispatch_barrier_async(queue1, ^{
        NSLog(@"barrier");
    });
    dispatch_async(queue1, ^{
        NSLog(@"4");
    });
    dispatch_async(queue1, ^{
        NSLog(@"5");
    });
輸出:其中前3個block是亂序 等前3個完成后執(zhí)行屏障block 屏障block完成后 亂序執(zhí)行后兩個block
1
3
2
barrier
5
4
  • 提交屏障block到調(diào)度隊列queue上并同步執(zhí)行。(會先等待queue中的異步項執(zhí)行完成)
void dispatch_barrier_async_and_wait(dispatch_queue_t queue, dispatch_block_t block);

只對用DISPATCH_QUEUE_CONCURRENT創(chuàng)建的隊列有作用超燃,否則與dispatch_async_and_wait效果相同区拳。
因為dispatch_barrier_async_and_wait中的async_and_wait的作用是等待隊列中async的block執(zhí)行完成,dispatch_barrier_async_and_wait中的barrier作用是等待之前所有blcok執(zhí)行意乓,所以dispatch_barrier_async_and_wait的功能為等待所有同步或異步的block都執(zhí)行完成樱调。

  • 提交屏障函數(shù)work到調(diào)度隊列queue上并同步執(zhí)行。(會先等待queue中的異步項執(zhí)行完成)
void dispatch_barrier_async_and_wait_f(dispatch_queue_t queue,
        void *_Nullable context, dispatch_function_t work);

只對用DISPATCH_QUEUE_CONCURRENT創(chuàng)建的隊列有作用届良,否則與dispatch_async_and_wait_f效果相同笆凌。

  • 給調(diào)度隊列queue設(shè)置對應(yīng)鍵值key的上下文context。
void dispatch_queue_set_specific(dispatch_queue_t queue, const void *key,
        void *_Nullable context, dispatch_function_t _Nullable destructor);

當(dāng)為同一key設(shè)置新上下文context時士葫,或者在釋放對隊列的所有引用之后乞而,將使用默認(rèn)優(yōu)先級全局并發(fā)隊列dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)上的上下文并調(diào)用函數(shù)destructor。
key 設(shè)置上下文的鍵值

  • 通過鍵值key獲取調(diào)度隊列queue的上下文context慢显。
void *_Nullable dispatch_queue_get_specific(dispatch_queue_t queue, const void *key);

key 獲取上下文的鍵值

  • 通過對應(yīng)鍵值key獲取當(dāng)前隊列的上下文context爪模。
void *_Nullable dispatch_get_specific(const void *key);

key 獲取上下文的鍵值

例:
    dispatch_queue_t queue1 = dispatch_queue_create("queue1", DISPATCH_QUEUE_SERIAL);
    int context = 10;
    dispatch_queue_set_specific(queue1, "key", &context, work);
    int context1 = 11;
    dispatch_queue_set_specific(queue1, "key1", &context1, work);
    int *adress1 = dispatch_queue_get_specific(queue1, "key");
    int *adress2 = dispatch_queue_get_specific(queue1, "key1");
    NSLog(@"%d %d", *adress1, *adress2);
    dispatch_sync(queue1, ^{
        int *adress1 = dispatch_get_specific("key");
        int *adress2 = dispatch_get_specific("key1");
        NSLog(@"%d %d", *adress1, *adress2);
    });
    dispatch_async(queue1, ^{
        int *adress1 = dispatch_get_specific("key");
        int *adress2 = dispatch_get_specific("key1");
        NSLog(@"%d %d", *adress1, *adress2);
    });

void work(void *context) {

}
輸出:可以看出dispatch_sync同步時獲取的context是相同的,而異步時卻不同荚藻,不知為何屋灌。
10 11
10 11
0 0
例:
    const void *key = "key";
    dispatch_queue_t queue1 = dispatch_queue_create(key, DISPATCH_QUEUE_SERIAL);
    dispatch_queue_set_specific(queue1, key, &key, NULL);
    dispatch_async(queue1, ^{
        if (dispatch_get_specific(key)) {
            NSLog(@"當(dāng)前的隊列是queue1");
        } else{
            NSLog(@"當(dāng)前的隊列不是queue1");
        }
    });
輸出:可通過該方式判斷當(dāng)前隊列
當(dāng)前的隊列是queue1
  • 驗證當(dāng)前的block是否在調(diào)度隊列queue上執(zhí)行。
void dispatch_assert_queue(dispatch_queue_t queue);

如果當(dāng)前正在執(zhí)行的block已提交到隊列queue或任何以它為目標(biāo)的隊列dispatch_set_target_queue应狱,則此函數(shù)返回共郭,代碼繼續(xù)運行。否則疾呻,該方法會觸發(fā)斷定NSAssert除嘹。
該方法請僅在調(diào)試中使用。

  • 驗證當(dāng)前的block是否在調(diào)度隊列queue上執(zhí)行岸蜗,并且將block充當(dāng)隊列queue上的屏障block憾赁。
void dispatch_assert_queue_barrier(dispatch_queue_t queue);

屏障的作用詳見dispatch_barrier_async

  • 驗證當(dāng)前的block是否不在調(diào)度隊列queue上執(zhí)行。
void dispatch_assert_queue_not(dispatch_queue_t queue)

dispatch_assert_queue功能相反

例:
dispatch_queue_t queue1 = dispatch_queue_create("queue1", DISPATCH_QUEUE_SERIAL);
    dispatch_async(queue1, ^{
        NSLog(@"1");
        dispatch_assert_queue(queue1);
        NSLog(@"2");
        [NSThread sleepForTimeInterval:1];
    });
    dispatch_assert_queue(dispatch_get_main_queue());
    dispatch_assert_queue_not(queue1);
    NSLog(@"3");
輸出:
3
1
2
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末散吵,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌矾睦,老刑警劉巖晦款,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異枚冗,居然都是意外死亡缓溅,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進店門赁温,熙熙樓的掌柜王于貴愁眉苦臉地迎上來坛怪,“玉大人,你說我怎么就攤上這事股囊⊥嗄洌” “怎么了?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵稚疹,是天一觀的道長居灯。 經(jīng)常有香客問我,道長内狗,這世上最難降的妖魔是什么怪嫌? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮柳沙,結(jié)果婚禮上岩灭,老公的妹妹穿的比我還像新娘。我一直安慰自己赂鲤,他們只是感情好噪径,可當(dāng)我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蛤袒,像睡著了一般熄云。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上妙真,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天缴允,我揣著相機與錄音,去河邊找鬼珍德。 笑死练般,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的锈候。 我是一名探鬼主播薄料,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼泵琳!你這毒婦竟也來了摄职?” 一聲冷哼從身側(cè)響起誊役,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎谷市,沒想到半個月后蛔垢,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡迫悠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年鹏漆,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片创泄。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡艺玲,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出鞠抑,到底是詐尸還是另有隱情饭聚,我是刑警寧澤,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布碍拆,位于F島的核電站若治,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏感混。R本人自食惡果不足惜端幼,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望弧满。 院中可真熱鬧婆跑,春花似錦、人聲如沸庭呜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽募谎。三九已至扶关,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間数冬,已是汗流浹背节槐。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留拐纱,地道東北人铜异。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像秸架,于是被迫代替她去往敵國和親揍庄。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,592評論 2 353