說明:本文主要用于個人能力的提高讳侨,主要參考于簡書搀捷,Swift版本為3.0
1. 簡介
什么是GCD呢艾少?我們先看看百度百科的解釋了解下概念
引用百度百科
Grand Central Dispatch (GCD) 是Apple開發(fā)的一個多核編程的較新的解決方法默怨。它主要用于優(yōu)化應(yīng)用程序以支持多核處理器以及其他對稱多處理系統(tǒng)樟氢。它是一個在線程池模式的基礎(chǔ)上執(zhí)行的并行任務(wù)。在Mac OS X 10.6雪豹中首次推出镇饺,也可在IOS 4及以上版本使用。
為什么要用GCD呢送讲?
因為GCD有很多好處奸笤,具體如下:
- GCD可用于多核的并行運算
- GCD會自動利用更多的CPU內(nèi)核(比如雙核惋啃、四核)
- GCD會自動管理線程的生命周期(創(chuàng)建線程、調(diào)度任務(wù)监右、銷毀線程)
- 程序員只需要告訴GCD想要執(zhí)行什么任務(wù)边灭,不需要編寫任何線程管理代碼
既然GCD有這么多的好處,那么下面我們就來系統(tǒng)的學(xué)習(xí)一下GCD的使用方法健盒。
2.任務(wù)和隊列
學(xué)習(xí)GCD之前绒瘦,先來了解GCD中兩個核心概念:任務(wù)和隊列
任務(wù): 就是執(zhí)行操作的意思,換句話說就是你在線程中執(zhí)行的那段代碼扣癣。在GCD中是放在block中的惰帽,swift是放在閉包中的。執(zhí)行任務(wù)有兩種方式:同步執(zhí)行和異步執(zhí)行父虑。兩者的主要區(qū)別是:是否具備開啟新線程的能力该酗。
- 同步執(zhí)行(sync):只能在當(dāng)前線程中執(zhí)行任務(wù),不具備開啟新線程的能力
- 異步執(zhí)行(async):可以在新的線程中執(zhí)行任務(wù)士嚎,具備開啟新線程的能力
隊列:這里的隊列指任務(wù)隊列呜魄,即用來存放任務(wù)的隊列。隊列是一種特殊的線性表莱衩,采用FIFO(先進(jìn)先出)的原則爵嗅,即新任務(wù)總是被插入到隊列的末尾,而讀取任務(wù)的時候總是從隊列的頭部開始讀取笨蚁。每讀取一個任務(wù)睹晒,則從隊列中釋放一個任務(wù)。在GCD中有兩種隊列:串行隊列和并行隊列赚窃。
- 并行隊列(Concurrent Dispatch Queue):可以讓多個任務(wù)并行(同時)執(zhí)行(自動開啟多個線程同時執(zhí)行任務(wù))
- 并行功能只有在異步(dispatch_async)函數(shù)下才有效
- 串行隊列(Serial Dispatch Queue):讓任務(wù)一個接著一個地執(zhí)行(一個任務(wù)執(zhí)行完畢后册招,再執(zhí)行下一個任務(wù))
3.GCD的使用步驟
GCD的使用步驟其實很簡單,只有兩步勒极。
- 創(chuàng)建一個隊列(串行隊列或并行隊列)
- 將任務(wù)添加到隊列中是掰,然后系統(tǒng)就會根據(jù)任務(wù)類型執(zhí)行任務(wù)(同步執(zhí)行或異步執(zhí)行)
下面來看看隊列的創(chuàng)建和任務(wù)的創(chuàng)建方法室奏。
1. 隊列的創(chuàng)建方法
OC版本:
- 可以使用
dispatch_queue_create
來創(chuàng)建對象妨蛹,需要傳入兩個參數(shù)讥邻,第一個參數(shù)表示隊列的唯一標(biāo)識符责蝠,用于DEBUG矩欠,可為空钮热;第二個參數(shù)用來識別是串行隊列還是并行隊列髓棋。DISPATCH_QUEUE_SERIAL
表示串行隊列喧锦,DISPATCH_QUEUE_CONCURRENT
表示并行隊列昨忆。
// 串行隊列的創(chuàng)建方法
dispatch_queue_t queue= dispatch_queue_create("test.queue", DISPATCH_QUEUE_SERIAL);
// 并行隊列的創(chuàng)建方法
dispatch_queue_t queue= dispatch_queue_create("test.queue", DISPATCH_QUEUE_CONCURRENT);
- 對于并行隊列丁频,還可以使用
dispatch_get_global_queue
來創(chuàng)建全局并行隊列。GCD默認(rèn)提供了全局的并行隊列,需要傳入兩個參數(shù)席里。第一個參數(shù)表示隊列優(yōu)先級叔磷,一般用DISPATCH_QUEUE_PRIORITY_DEFAULT
。第二個參數(shù)暫時沒用奖磁,用0
即可改基。
Swift版本:
- 在使用Swift編碼時,可以使用
DispatchQueue
來創(chuàng)建對象咖为,第一個參數(shù)與OC相同秕狰,為標(biāo)識符,其他參數(shù)均可省略躁染。當(dāng)僅有一個label
參數(shù)時鸣哀,默認(rèn)為串行隊列,當(dāng)設(shè)置了attributes
為.concurrent
時為并行隊列褐啡。
// 創(chuàng)建串行隊列
let queue = DispatchQueue(label: "test.queue")
// 創(chuàng)建并行隊列
let queue = DispatchQueue(label: "test.queue", attributes: .concurrent)
2. 任務(wù)的創(chuàng)建方法
OC版本:
// 同步執(zhí)行任務(wù)創(chuàng)建方法
dispatch_sync(queue, ^{
NSLog(@"%@",[NSThread currentThread]); // 這里放任務(wù)代碼
});
// 異步執(zhí)行任務(wù)創(chuàng)建方法
dispatch_async(queue, ^{
NSLog(@"%@",[NSThread currentThread]); // 這里放任務(wù)代碼
});
Swift版本:
// 同步執(zhí)行任務(wù)創(chuàng)建方法
queue.sync {
print(Thread.current)
}
// 異步執(zhí)行任務(wù)創(chuàng)建方法
queue.async {
print(Thread.current)
}
雖然使用GCD只有兩步诺舔,但是既然我們有兩種隊列,兩種任務(wù)執(zhí)行方式备畦,那么我們就有了四種不同的組合方式低飒。這四種不同的組合方式是:
- 并行隊列 + 同步執(zhí)行
- 并行隊列 + 異步執(zhí)行
- 串行隊列 + 同步執(zhí)行
- 串行隊列 + 異步執(zhí)行
實際上我們還有一種特殊的主隊列,那就有六種不同的組合方式了
- 主隊列 + 同步執(zhí)行
- 主隊列 + 異步執(zhí)行
那么這幾種不同組合方式有什么區(qū)別呢懂盐,這里為了方便褥赊,先上結(jié)果,再來講解莉恼。為圖省事拌喉,直接查看表格結(jié)果,然后可以跳過4. GCD的基本使用 了俐银。
并行隊列 | 串行隊列 | 主隊列 | |
---|---|---|---|
同步(sync) | 沒有開啟新線程尿背,串行執(zhí)行任務(wù) | 沒有開啟新線程,串行執(zhí)行任務(wù) | 沒有開啟新線程捶惜,串行執(zhí)行任務(wù) |
異步(async) | 有開啟新線程田藐,并行執(zhí)行任務(wù) | 有開啟新線程(1條),串行執(zhí)行任務(wù) | 沒有開啟新線程吱七,串行執(zhí)行任務(wù) |
4. GCD的基本使用
先來講講并行隊列的兩種使用方法汽久。
1. 并行隊列 + 同步執(zhí)行
- 不會開啟新線程,執(zhí)行完一個任務(wù)踊餐,再執(zhí)行下一個任務(wù)
OC版本:
- (void)syncConcurrentMethod{
NSLog(@"syncConcurrentMethod---begin");
dispatch_queue_t queue= dispatch_queue_create("test.queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_sync(queue, ^{
for (int i = 0; i < 2; ++i) {
NSLog(@"1------%@",[NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
for (int i = 0; i < 2; ++i) {
NSLog(@"2------%@",[NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
for (int i = 0; i < 2; ++i) {
NSLog(@"3------%@",[NSThread currentThread]);
}
});
NSLog(@"syncConcurrentMethod---end");
}
輸出結(jié)果:
2017-09-19 10:57:34.223 OC-GCD[1824:54181] syncConcurrentMethod---begin
2017-09-19 10:57:34.223 OC-GCD[1824:54181] 1------<NSThread: 0x61800006d000>{number = 1, name = main}
2017-09-19 10:57:34.223 OC-GCD[1824:54181] 1------<NSThread: 0x61800006d000>{number = 1, name = main}
2017-09-19 10:57:34.223 OC-GCD[1824:54181] 2------<NSThread: 0x61800006d000>{number = 1, name = main}
2017-09-19 10:57:34.223 OC-GCD[1824:54181] 2------<NSThread: 0x61800006d000>{number = 1, name = main}
2017-09-19 10:57:34.224 OC-GCD[1824:54181] 3------<NSThread: 0x61800006d000>{number = 1, name = main}
2017-09-19 10:57:34.224 OC-GCD[1824:54181] 3------<NSThread: 0x61800006d000>{number = 1, name = main}
2017-09-19 10:57:34.224 OC-GCD[1824:54181] syncConcurrentMethod---end
Swift版本:
func syncConcurrentMethod() {
print("syncConcurrentMethod---begin")
let queue = DispatchQueue(label: "test.queue", attributes: .concurrent)
queue.sync {
for _ in 0..<2 {
print("1------",Thread.current)
}
}
queue.sync {
for _ in 0..<2 {
print("2------",Thread.current)
}
}
queue.sync {
for _ in 0..<2 {
print("3------",Thread.current)
}
}
print("syncConcurrentMethod---end")
}
輸出結(jié)果:
syncConcurrentMethod---begin
1------ <NSThread: 0x61000006a440>{number = 1, name = main}
1------ <NSThread: 0x61000006a440>{number = 1, name = main}
2------ <NSThread: 0x61000006a440>{number = 1, name = main}
2------ <NSThread: 0x61000006a440>{number = 1, name = main}
3------ <NSThread: 0x61000006a440>{number = 1, name = main}
3------ <NSThread: 0x61000006a440>{number = 1, name = main}
syncConcurrentMethod---end
- 從
并行隊列 + 同步執(zhí)行
中可以看到景醇,所有任務(wù)都是在主線程中執(zhí)行的,由于只有一個線程吝岭,所以任務(wù)只能一個一個執(zhí)行三痰。 - 同事我們還可以看到吧寺,所有任務(wù)都在打印的
syncConcurrentMethod---begin
和syncConcurrentMethod---end
之間,這說明任務(wù)是添加到隊列中馬上執(zhí)行的酒觅。
2. 并行隊列 + 異步執(zhí)行
- 可同時開啟多線程撮执,任務(wù)交替執(zhí)行
OC版本:
- (void)asyncConcurrentMethod{
NSLog(@"asyncConcurrentMethod---begin");
dispatch_queue_t queue= dispatch_queue_create("test.queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
for (int i = 0; i < 2; ++i) {
NSLog(@"1------%@",[NSThread currentThread]);
}
});
dispatch_async(queue, ^{
for (int i = 0; i < 2; ++i) {
NSLog(@"2------%@",[NSThread currentThread]);
}
});
dispatch_async(queue, ^{
for (int i = 0; i < 2; ++i) {
NSLog(@"3------%@",[NSThread currentThread]);
}
});
NSLog(@"asyncConcurrentMethod---end");
}
輸出結(jié)果:
2017-09-19 11:16:35.521 OC-GCD[2301:67293] asyncConcurrentMethod---begin
2017-09-19 11:16:35.521 OC-GCD[2301:67293] asyncConcurrentMethod---end
2017-09-19 11:16:35.521 OC-GCD[2301:67348] 1------<NSThread: 0x608000073e00>{number = 3, name = (null)}
2017-09-19 11:16:35.521 OC-GCD[2301:67719] 2------<NSThread: 0x6000000787c0>{number = 4, name = (null)}
2017-09-19 11:16:35.521 OC-GCD[2301:67720] 3------<NSThread: 0x6180000790c0>{number = 5, name = (null)}
2017-09-19 11:16:35.522 OC-GCD[2301:67348] 1------<NSThread: 0x608000073e00>{number = 3, name = (null)}
2017-09-19 11:16:35.522 OC-GCD[2301:67719] 2------<NSThread: 0x6000000787c0>{number = 4, name = (null)}
2017-09-19 11:16:35.522 OC-GCD[2301:67720] 3------<NSThread: 0x6180000790c0>{number = 5, name = (null)}
Swift版本:
func asyncConcurrentMethod() {
print("asyncConcurrentMethod---begin")
let queue = DispatchQueue(label: "test.queue", attributes: .concurrent)
queue.async {
for _ in 0..<2 {
print("1------",Thread.current)
}
}
queue.async {
for _ in 0..<2 {
print("2------",Thread.current)
}
}
queue.async {
for _ in 0..<2 {
print("3------",Thread.current)
}
}
print("asyncConcurrentMethod---end")
}
輸出結(jié)果:
asyncConcurrentMethod---begin
asyncConcurrentMethod---end
1------ <NSThread: 0x61000007e700>{number = 3, name = (null)}
2------ <NSThread: 0x60800007eac0>{number = 4, name = (null)}
3------ <NSThread: 0x60800007ec00>{number = 5, name = (null)}
1------ <NSThread: 0x61000007e700>{number = 3, name = (null)}
2------ <NSThread: 0x60800007eac0>{number = 4, name = (null)}
3------ <NSThread: 0x60800007ec00>{number = 5, name = (null)}
- 在
并行隊列 + 異步執(zhí)行
中可以看出,除了主線程舷丹,又新開啟了3個新線程,并且任務(wù)是交替著同時進(jìn)行的蜓肆。 - 另一方面可以看出颜凯,所有任務(wù)是在打印的
asyncConcurrentMethod---begin
和asyncConcurrentMethod---end
之后才開始執(zhí)行的。說明任務(wù)不是馬上執(zhí)行仗扬,而是將所有任務(wù)添加到隊列之后才開始異步執(zhí)行的症概。
3. 串行隊列 + 同步執(zhí)行
- 不會開啟新線程,在當(dāng)前線程執(zhí)行任務(wù)早芭。任務(wù)是串行的彼城,執(zhí)行完一個任務(wù),再執(zhí)行下一個任務(wù)退个。
OC版本:
- (void) syncSerialMethod {
NSLog(@"syncSerialMethod---begin");
dispatch_queue_t queue = dispatch_queue_create("test.queue", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue, ^{
for (int i = 0; i < 2; ++i) {
NSLog(@"1------%@",[NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
for (int i = 0; i < 2; ++i) {
NSLog(@"2------%@",[NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
for (int i = 0; i < 2; ++i) {
NSLog(@"3------%@",[NSThread currentThread]);
}
});
NSLog(@"syncSerialMethod---end");
}
輸出結(jié)果:
2017-09-19 11:35:00.774 OC-GCD[2699:78730] syncSerialMethod---begin
2017-09-19 11:35:00.775 OC-GCD[2699:78730] 1------<NSThread: 0x6100000641c0>{number = 1, name = main}
2017-09-19 11:35:00.775 OC-GCD[2699:78730] 1------<NSThread: 0x6100000641c0>{number = 1, name = main}
2017-09-19 11:35:00.775 OC-GCD[2699:78730] 2------<NSThread: 0x6100000641c0>{number = 1, name = main}
2017-09-19 11:35:00.775 OC-GCD[2699:78730] 2------<NSThread: 0x6100000641c0>{number = 1, name = main}
2017-09-19 11:35:00.775 OC-GCD[2699:78730] 3------<NSThread: 0x6100000641c0>{number = 1, name = main}
2017-09-19 11:35:00.776 OC-GCD[2699:78730] 3------<NSThread: 0x6100000641c0>{number = 1, name = main}
2017-09-19 11:35:00.776 OC-GCD[2699:78730] syncSerialMethod---end
Swift版本:
func syncSerialMethod() {
print("syncSerialMethod---begin")
let queue = DispatchQueue(label: "test.queue")
queue.sync {
for _ in 0..<2 {
print("1------",Thread.current)
}
}
queue.sync {
for _ in 0..<2 {
print("2------",Thread.current)
}
}
queue.sync {
for _ in 0..<2 {
print("3------",Thread.current)
}
}
print("syncSerialMethod---end")
}
輸出結(jié)果:
syncSerialMethod---begin
1------ <NSThread: 0x6080000757c0>{number = 1, name = main}
1------ <NSThread: 0x6080000757c0>{number = 1, name = main}
2------ <NSThread: 0x6080000757c0>{number = 1, name = main}
2------ <NSThread: 0x6080000757c0>{number = 1, name = main}
3------ <NSThread: 0x6080000757c0>{number = 1, name = main}
3------ <NSThread: 0x6080000757c0>{number = 1, name = main}
syncSerialMethod---end
- 在
串行隊列 + 同步執(zhí)行
可以看到募壕,所有任務(wù)都是在主線程中執(zhí)行的,并沒有開啟新的線程语盈。而且由于串行隊列舱馅,所以按順序一個一個執(zhí)行。 - 同時我們還可以看到刀荒,所有任務(wù)都在打印的
syncSerialMethod---begin
和syncSerialMethod---end
之間代嗤,說明任務(wù)是添加到隊列中,并馬上執(zhí)行的缠借。
4. 串行隊列 + 異步執(zhí)行
- 會開啟新線程干毅,但是因為任務(wù)是串行的,執(zhí)行完一個任務(wù)泼返,再執(zhí)行下一個任務(wù)
OC版本:
- (void) asyncSerialMethod{
NSLog(@"asyncSerialMethod---begin");
dispatch_queue_t queue = dispatch_queue_create("test.queue", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
for (int i = 0; i < 2; ++i) {
NSLog(@"1------%@",[NSThread currentThread]);
}
});
dispatch_async(queue, ^{
for (int i = 0; i < 2; ++i) {
NSLog(@"2------%@",[NSThread currentThread]);
}
});
dispatch_async(queue, ^{
for (int i = 0; i < 2; ++i) {
NSLog(@"3------%@",[NSThread currentThread]);
}
});
NSLog(@"asyncSerialMethod---end");
}
輸出結(jié)果:
2017-09-19 11:54:29.808 OC-GCD[3018:88451] asyncSerialMethod---begin
2017-09-19 11:54:29.808 OC-GCD[3018:88451] asyncSerialMethod---end
2017-09-19 11:54:29.808 OC-GCD[3018:88506] 1------<NSThread: 0x600000068940>{number = 3, name = (null)}
2017-09-19 11:54:29.809 OC-GCD[3018:88506] 1------<NSThread: 0x600000068940>{number = 3, name = (null)}
2017-09-19 11:54:29.809 OC-GCD[3018:88506] 2------<NSThread: 0x600000068940>{number = 3, name = (null)}
2017-09-19 11:54:29.809 OC-GCD[3018:88506] 2------<NSThread: 0x600000068940>{number = 3, name = (null)}
2017-09-19 11:54:29.809 OC-GCD[3018:88506] 3------<NSThread: 0x600000068940>{number = 3, name = (null)}
2017-09-19 11:54:29.809 OC-GCD[3018:88506] 3------<NSThread: 0x600000068940>{number = 3, name = (null)}
Swift版本:
func asyncSerialMethod() {
print("asyncSerialMethod---begin")
let queue = DispatchQueue(label: "test.queue")
queue.async {
for _ in 0..<2 {
print("1------",Thread.current)
}
}
queue.async {
for _ in 0..<2 {
print("2------",Thread.current)
}
}
queue.async {
for _ in 0..<2 {
print("3------",Thread.current)
}
}
print("asyncSerialMethod---end")
}
輸出結(jié)果:
asyncSerialMethod---begin
asyncSerialMethod---end
1------ <NSThread: 0x600000267c80>{number = 3, name = (null)}
1------ <NSThread: 0x600000267c80>{number = 3, name = (null)}
2------ <NSThread: 0x600000267c80>{number = 3, name = (null)}
2------ <NSThread: 0x600000267c80>{number = 3, name = (null)}
3------ <NSThread: 0x600000267c80>{number = 3, name = (null)}
3------ <NSThread: 0x600000267c80>{number = 3, name = (null)}
- 在
串行隊列 + 異步執(zhí)行
可以看到硝逢,開啟了一條新線程,但是任務(wù)還是串行符隙,所以任務(wù)是一個一個執(zhí)行趴捅。 - 另一方面可以看出,所有哦任務(wù)是在打印的
asyncSerialMethod---begin
和asyncSerialMethod---end
之后才開始執(zhí)行的霹疫。說明任務(wù)不是馬上執(zhí)行拱绑,而是將所有任務(wù)添加到隊列之后才開始異步執(zhí)行的。
然后講講剛才提到過的特殊隊列——主隊列
- 主隊列:GCD自帶的一種特殊的串行隊列
- 所有放在主隊列中的任務(wù)丽蝎,都會放到主線程中執(zhí)行
- OC可以使用
dispatch_get_main_queue()
獲得主隊列猎拨,Swift可以使用DispatchQueue.main
獲得
再來看看主隊列的兩種組合方式
5. 主隊列 + 同步執(zhí)行
- 相互等待膀藐,造成死鎖(在主線程中調(diào)用時)
OC版本:
- (void)syncMainMethod{
NSLog(@"syncMainMethod---begin");
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_sync(queue, ^{
for (int i = 0; i < 2; ++i) {
NSLog(@"1------%@",[NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
for (int i = 0; i < 2; ++i) {
NSLog(@"2------%@",[NSThread currentThread]);
}
});
dispatch_sync(queue, ^{
for (int i = 0; i < 2; ++i) {
NSLog(@"3------%@",[NSThread currentThread]);
}
});
NSLog(@"syncMainMethod---end");
}
輸出結(jié)果:
2017-09-19 14:20:14.826 OC-GCD[4057:146416] syncMainMethod---begin
(lldb)
Swift版本:
func syncMainMethod() {
print("syncMainMethod---begin")
let queue = DispatchQueue.main
queue.sync {
for _ in 0..<2 {
print("1------",Thread.current)
}
}
queue.sync {
for _ in 0..<2 {
print("2------",Thread.current)
}
}
queue.sync {
for _ in 0..<2 {
print("3------",Thread.current)
}
}
print("syncMainMethod---end")
}
輸出結(jié)果:
syncMainMethod---begin
(lldb)
這時候,我們可以發(fā)現(xiàn)红省,在主線程中使用主隊列 + 同步執(zhí)行
额各,任務(wù)不再執(zhí)行了,而syncMainMethod---end
也沒有打印了吧恃,這是什么原因?qū)е碌哪兀?/p>
這是因為我們在主線中執(zhí)行這段代碼虾啦。我們把任務(wù)放到了主隊列中,也就是放到了主線程的隊列中痕寓。而同步執(zhí)行有個特點傲醉,就是對于任務(wù)是立馬執(zhí)行的。那么當(dāng)我們把第一個任務(wù)放進(jìn)主隊列中呻率,它會立即執(zhí)行硬毕。但是對于主線程現(xiàn)在正在處理syncMainMethod
方法,而任務(wù)又需要等syncMainMethod
方法執(zhí)行結(jié)束才能執(zhí)行礼仗。而syncMainMethod
執(zhí)行到第一個任務(wù)的時候吐咳,又要等第一個任務(wù)執(zhí)行完才能玩下執(zhí)行第二和第三個任務(wù)。簡單來說元践,就是syncMainMethod
方法結(jié)束后才能執(zhí)行第一個同步任務(wù)韭脊,而第一個同步任務(wù)又在syncMainMethod
方法中,需要執(zhí)行了本任務(wù)之后卢厂,才能繼續(xù)執(zhí)行其他任務(wù)乾蓬,直到syncMainMethod
方法完全結(jié)束,相互等待慎恒,造成了死鎖任内。
那么,現(xiàn)在的情況就是第一個任務(wù)都在等對方執(zhí)行完畢融柬,造成了死鎖死嗦,所以我們的任務(wù)就執(zhí)行不了,而且syncMainMethod---end
也沒打印
要是如果不在主線程中調(diào)用粒氧,而在其他線程中調(diào)用會如何呢越除?
- 不會開啟新線程,執(zhí)行完一個任務(wù)外盯,再執(zhí)行下一個任務(wù)(在其他線程中調(diào)用)
OC版本:
dispatch_queue_t queue = dispatch_queue_create("test.queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
[self syncMainMethod];
});
輸出結(jié)果:
2017-09-19 14:51:03.723 OC-GCD[4483:161903] syncMainMethod---begin
2017-09-19 14:51:03.723 OC-GCD[4483:161788] 1------<NSThread: 0x60800007c500>{number = 1, name = main}
2017-09-19 14:51:03.724 OC-GCD[4483:161788] 1------<NSThread: 0x60800007c500>{number = 1, name = main}
2017-09-19 14:51:03.724 OC-GCD[4483:161788] 2------<NSThread: 0x60800007c500>{number = 1, name = main}
2017-09-19 14:51:03.724 OC-GCD[4483:161788] 2------<NSThread: 0x60800007c500>{number = 1, name = main}
2017-09-19 14:51:03.724 OC-GCD[4483:161788] 3------<NSThread: 0x60800007c500>{number = 1, name = main}
2017-09-19 14:51:03.724 OC-GCD[4483:161788] 3------<NSThread: 0x60800007c500>{number = 1, name = main}
2017-09-19 14:51:03.724 OC-GCD[4483:161903] syncMainMethod---end
Swift版本:
let queue = DispatchQueue(label: "test.queue", attributes: .concurrent)
queue.async {
self.syncMainMethod()
}
輸出結(jié)果:
syncMainMethod---begin
1------ <NSThread: 0x61800007aa40>{number = 1, name = main}
1------ <NSThread: 0x61800007aa40>{number = 1, name = main}
2------ <NSThread: 0x61800007aa40>{number = 1, name = main}
2------ <NSThread: 0x61800007aa40>{number = 1, name = main}
3------ <NSThread: 0x61800007aa40>{number = 1, name = main}
3------ <NSThread: 0x61800007aa40>{number = 1, name = main}
syncMainMethod---end
- 在其他線程中使用
主隊列 + 同步執(zhí)行
可以看到:所有任務(wù)都是在主線程中執(zhí)行的摘盆,并沒有開啟新線程。而且由于主隊列是串行隊列饱苟,可以按照順序一個一個執(zhí)行孩擂。 - 同時我們還可以看到,所有任務(wù)都在打印的
syncConcurrent---begin
和syncConcurrent---end
之間箱熬,說明任務(wù)是添加到隊列中馬上執(zhí)行的类垦。
6. 主隊列 + 異步執(zhí)行
- 只有在主線程中執(zhí)行任務(wù)狈邑,執(zhí)行完一個任務(wù),再執(zhí)行下一個任務(wù)
OC版本:
- (void)asyncMainMethod{
NSLog(@"asyncMainMethod---begin");
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_async(queue, ^{
for (int i = 0; i < 2; ++i) {
NSLog(@"1------%@",[NSThread currentThread]);
}
});
dispatch_async(queue, ^{
for (int i = 0; i < 2; ++i) {
NSLog(@"2------%@",[NSThread currentThread]);
}
});
dispatch_async(queue, ^{
for (int i = 0; i < 2; ++i) {
NSLog(@"3------%@",[NSThread currentThread]);
}
});
NSLog(@"asyncMainMethod---end");
}
輸出結(jié)果:
2017-09-19 22:30:10.807 OC-GCD[1151:23348] asyncMainMethod---begin
2017-09-19 22:30:10.808 OC-GCD[1151:23348] asyncMainMethod---end
2017-09-19 22:30:10.809 OC-GCD[1151:23348] 1------<NSThread: 0x60000006e500>{number = 1, name = main}
2017-09-19 22:30:10.810 OC-GCD[1151:23348] 1------<NSThread: 0x60000006e500>{number = 1, name = main}
2017-09-19 22:30:10.810 OC-GCD[1151:23348] 2------<NSThread: 0x60000006e500>{number = 1, name = main}
2017-09-19 22:30:10.810 OC-GCD[1151:23348] 2------<NSThread: 0x60000006e500>{number = 1, name = main}
2017-09-19 22:30:10.810 OC-GCD[1151:23348] 3------<NSThread: 0x60000006e500>{number = 1, name = main}
2017-09-19 22:30:10.810 OC-GCD[1151:23348] 3------<NSThread: 0x60000006e500>{number = 1, name = main}
Swift版本:
func asyncMainMethod() {
print("asyncMainMethod---begin")
let queue = DispatchQueue.main
queue.async {
for _ in 0..<2 {
print("1------",Thread.current)
}
}
queue.async {
for _ in 0..<2 {
print("2------",Thread.current)
}
}
queue.async {
for _ in 0..<2 {
print("3------",Thread.current)
}
}
print("asyncMainMethod---end")
}
輸出結(jié)果:
asyncMainMethod---begin
asyncMainMethod---end
1------ <NSThread: 0x6080000707c0>{number = 1, name = main}
1------ <NSThread: 0x6080000707c0>{number = 1, name = main}
2------ <NSThread: 0x6080000707c0>{number = 1, name = main}
2------ <NSThread: 0x6080000707c0>{number = 1, name = main}
3------ <NSThread: 0x6080000707c0>{number = 1, name = main}
3------ <NSThread: 0x6080000707c0>{number = 1, name = main}
- 我們可以發(fā)現(xiàn)所有任務(wù)都在主線程鐘蚤认,雖然是異步執(zhí)行米苹,具備開啟線程的能力,但是因為是主隊列砰琢,所以所有任務(wù)都在主線程中蘸嘶,并且一個接一個執(zhí)行。
- 另一方面可以看出陪汽,所有任務(wù)是在打印的
asyncMainMethod---begin
和asyncMainMethod---end
之后才開始執(zhí)行的亏较。說明任務(wù)不是馬上執(zhí)行,而是將所有任務(wù)添加到隊列之后才開始同步執(zhí)行掩缓。