版本:iOS13.5
queue.h
同步和異步的區(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_resume
、dispatch_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.h的dispatch_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_activate
或dispatch_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_t
和dispatch_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