GCD的介紹
GCD(Grand Central Dispatch)中文名稱為“中央調(diào)度”或“大中央派發(fā)”等喝峦,是一個多核編程的解決方法樟氢。主要用于優(yōu)化應(yīng)用程序支持多核處理器以及其他對稱多處理系統(tǒng)谭期。是一個在線程池模式的基礎(chǔ)上執(zhí)行的并行任務(wù)缩抡。
在iOS開發(fā)中, 類似于GCD還有NSThread, NSOperation & NSOperationQueue等签餐。
GCD優(yōu)點
- GCD會自動利用更多的CPU內(nèi)核菱鸥;
- GCD可以用在多核并行運算;
- GCD會自動管理線程的生命周期, 比如創(chuàng)建線程, 調(diào)度任務(wù), 銷毀線程等操作抚垄。
GCD的任務(wù)和隊列
任務(wù)
任務(wù)是指放在GCD里的操作, 一般是用Block方式進行蜕窿。
執(zhí)行任務(wù)的操作有兩種, 同步執(zhí)行和異步執(zhí)行, 兩個的區(qū)別就是在是否開啟新線程進行操作。
同步執(zhí)行(sync) : 不會開啟新線程, 只會在當(dāng)前線程進行操作呆馁。
異步執(zhí)行(async): 可以另外開啟一個新的線程執(zhí)行任務(wù)桐经。
隊列
隊列指的是任務(wù)隊列, 用來存放任務(wù)的隊列。采用的是先進先出(FIFO)原則浙滤。
這里的隊列分為兩種, 并行隊列和串行隊列.
并行隊列(Concurrent Dispatch Queue): 可以讓多個任務(wù)同時執(zhí)行, 如果用到并行隊列的話, 是會自動開啟多個線程同時執(zhí)行任務(wù)阴挣。
串行隊列(Serial Dispatch Queue): 任務(wù)一個接一個的執(zhí)行, 完成了前面的任務(wù)再執(zhí)行后面的任務(wù)。
注意: 并行隊列只有在異步執(zhí)行(dispatch_async)才有效纺腊。
GCD的使用
1.創(chuàng)建隊列
可以使用dispatch_queue_create來創(chuàng)建對象
dispatch_queue_create(const char * _Nullable label, dispatch_queue_attr_t _Nullable attr)
第一個參數(shù): 隊列的唯一標(biāo)識符畔咧,表現(xiàn)形式可以是字符串如:“Queue”;
第二個參數(shù): 隊列的類型, 串行隊列(DISPATCH_QUEUE_SERIAL)或 并行隊列(DISPATCH_QUEUE_CONCURRENT)
// 創(chuàng)建串行隊列
dispatch_queue_t queue= dispatch_queue_create("Queue", DISPATCH_QUEUE_SERIAL);
// 創(chuàng)建并行隊列
dispatch_queue_t queue= dispatch_queue_create("Queue", DISPATCH_QUEUE_CONCURRENT);
常用的茎芭,并行隊列可以用全局并行隊列dispatch_get_global_queue(long identifier, unsigned long flags)創(chuàng)建。
第一個參數(shù): 隊列的優(yōu)先級, 一般都是用DISPATCH_QUEUE_PRIORITY_DEFAULT.
第二個參數(shù): 一般都是用0.
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
2.創(chuàng)建任務(wù)
// 創(chuàng)建同步執(zhí)行任務(wù)
dispatch_sync(queue, ^{
// service code
});
// 創(chuàng)建異步執(zhí)行任務(wù)
dispatch_async(queue, ^{
// service code
});
隊列和任務(wù)的組合:
同步執(zhí)行(sync) | 異步執(zhí)行(async) | |
---|---|---|
并行隊列 | 不開啟新線程, 串行方式執(zhí)行任務(wù) | 開啟新線程, 并行方式執(zhí)行任務(wù) |
串行隊列 | 不開啟新線程, 串行方式執(zhí)行任務(wù) | 開啟一條新線程, 串行方式執(zhí)行任務(wù) |
主隊列 | 不開啟新線程, 串行方式執(zhí)行任務(wù) | 不開啟新線程, 串行方式執(zhí)行任務(wù) |
CGD的基本使用
-
并行隊列同步執(zhí)行
- (void)dispatch_sync_queue_concurrent {
NSLog(@"Start working on a task");
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_sync(queue, ^{
NSLog(@"The first task of the current thread:%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"The second task of the current thread:%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"The third task of the current thread:%@",[NSThread currentThread]);
});
NSLog(@"Finish working on a task");
}
2017-08-12 14:34:57.299 GCDTest[1974:149023] Start working on a task
2017-08-12 14:34:57.299 GCDTest[1974:149023] The first task of the current thread:<NSThread: 0x608000078e40>{number = 1, name = main}
2017-08-12 14:34:57.299 GCDTest[1974:149023] The second task of the current thread:<NSThread: 0x608000078e40>{number = 1, name = main}
2017-08-12 14:34:57.300 GCDTest[1974:149023] The third task of the current thread:<NSThread: 0x608000078e40>{number = 1, name = main}
2017-08-12 14:34:57.300 GCDTest[1974:149023] Finish working on a task
- 當(dāng)前的線程都為同一條(main線程)盒卸,而且線程數(shù)只有1骗爆;
- 從執(zhí)行順序上, 并行隊列同步執(zhí)行是一個任務(wù)一個任務(wù)的去執(zhí)行的蔽介。
-
并行隊列異步執(zhí)行
- (void)dispatch_async_queue_concurrent {
NSLog(@"Start working on a task");
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSLog(@"The first task of the current thread:%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"The second task of the current thread:%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"The third task of the current thread:%@",[NSThread currentThread]);
});
NSLog(@"Finish working on a task");
}
2017-08-12 14:35:33.395 GCDTest[1974:149023] Start working on a task
2017-08-12 14:35:33.396 GCDTest[1974:149023] Finish working on a task
2017-08-12 14:35:33.396 GCDTest[1974:149163] The first task of the current thread:<NSThread: 0x6000002702c0>{number = 3, name = (null)}
2017-08-12 14:35:33.396 GCDTest[1974:149997] The second task of the current thread:<NSThread: 0x6000002705c0>{number = 4, name = (null)}
2017-08-12 14:35:33.396 GCDTest[1974:149998] The third task of the current thread:<NSThread: 0x608000265c40>{number = 5, name = (null)}
- 當(dāng)前的線程數(shù)有多條, 而且線程的名字未知摘投;
- 從時間上來看, 幾乎都是在同一時間執(zhí)行任務(wù)的;
- 并行隊列異步執(zhí)行的組合除了在主隊列上執(zhí)行, 還會另外開啟多幾條線程來并行執(zhí)行任務(wù)虹蓄。
-
串行隊列同步執(zhí)行
- (void)dispatch_sync_queue_serial {
NSLog(@"Start working on a task");
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue, ^{
NSLog(@"The first task of the current thread:%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"The second task of the current thread:%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"The third task of the current thread:%@",[NSThread currentThread]);
});
NSLog(@"Finish working on a task");
}
2017-08-12 14:36:08.965 GCDTest[1974:149023] Start working on a task
2017-08-12 14:36:08.966 GCDTest[1974:149023] The first task of the current thread:<NSThread: 0x608000078e40>{number = 1, name = main}
2017-08-12 14:36:08.966 GCDTest[1974:149023] The second task of the current thread:<NSThread: 0x608000078e40>{number = 1, name = main}
2017-08-12 14:36:08.966 GCDTest[1974:149023] The third task of the current thread:<NSThread: 0x608000078e40>{number = 1, name = main}
2017-08-12 14:36:08.966 GCDTest[1974:149023] Finish working on a task
- 從執(zhí)行順序上犀呼,串行隊列同步執(zhí)行是一個任務(wù)一個任務(wù)的去執(zhí)行的。
-
串行隊列異步執(zhí)行
- (void)dispatch_async_queue_serial {
NSLog(@"Start working on a task");
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
NSLog(@"The first task of the current thread:%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"The second task of the current thread:%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"The third task of the current thread:%@",[NSThread currentThread]);
});
NSLog(@"Finish working on a task");
}
2017-08-12 14:36:22.973 GCDTest[1974:149023] Start working on a task
2017-08-12 14:36:22.973 GCDTest[1974:149023] Finish working on a task
2017-08-12 14:36:22.974 GCDTest[1974:149163] The first task of the current thread:<NSThread: 0x6000002702c0>{number = 3, name = (null)}
2017-08-12 14:36:22.974 GCDTest[1974:149163] The second task of the current thread:<NSThread: 0x6000002702c0>{number = 3, name = (null)}
2017-08-12 14:36:22.974 GCDTest[1974:149163] The third task of the current thread:<NSThread: 0x6000002702c0>{number = 3, name = (null)}
- 開啟新線程來執(zhí)行任務(wù)薇组,由于是串行隊列外臂,所以任務(wù)還是一個接著一個來執(zhí)行。
- 任務(wù)并不是一下子就開始執(zhí)行的律胀,是需要將任務(wù)都添加到隊列里宋光,然后才開始同步執(zhí)行。
-
主隊列同步執(zhí)行
- (void)dispatch_sync_queue_main {
NSLog(@"Start working on a task");
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_sync(queue, ^{
NSLog(@"The first task of the current thread:%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"The second task of the current thread:%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"The third task of the current thread:%@",[NSThread currentThread]);
});
NSLog(@"Finish working on a task");
}
2017-08-12 14:36:43.542 GCDTest[1974:149023] Start working on a task
- 所有放在主隊列里執(zhí)行的任務(wù)都會放到主線程里執(zhí)行炭菌;
運行的時候出現(xiàn)異常, 系統(tǒng)崩潰~~~
同步執(zhí)行是一個一個任務(wù)去執(zhí)行的罪佳,當(dāng)主線程還在執(zhí)行 [self dispatch_sync_queue_main] 的時候,往主線程里添加任務(wù)黑低,這個時候就會出現(xiàn)異匙秆蓿現(xiàn)象,我們稱之為卡線程克握。
-
主隊列異步執(zhí)行
- (void)dispatch_async_queue_main {
NSLog(@"Start working on a task");
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_async(queue, ^{
NSLog(@"The first task of the current thread:%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"The second task of the current thread:%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"The third task of the current thread:%@",[NSThread currentThread]);
});
NSLog(@"Finish working on a task");
}
2017-08-12 14:37:08.303 GCDTest[2047:151940] Start working on a task
2017-08-12 14:37:08.303 GCDTest[2047:151940] Finish working on a task
2017-08-12 14:37:08.304 GCDTest[2047:151940] The first task of the current thread:<NSThread: 0x608000067d00>{number = 1, name = main}
2017-08-12 14:37:08.305 GCDTest[2047:151940] The second task of the current thread:<NSThread: 0x608000067d00>{number = 1, name = main}
2017-08-12 14:37:08.305 GCDTest[2047:151940] The third task of the current thread:<NSThread: 0x608000067d00>{number = 1, name = main}
- 所有放在主隊列里執(zhí)行的任務(wù)都會放到主線程里執(zhí)行蕾管。
- 雖然用的是異步執(zhí)行,具備了開啟新線程的能力菩暗,但是由于這是主隊列掰曾,所以所有的任務(wù)都是在主線程中,任務(wù)也是一個接著一個順序執(zhí)行停团。
- 任務(wù)并不是馬上就執(zhí)行的旷坦,而是把所有任務(wù)都添加到隊列里之后再執(zhí)行。