本文不說什么是GCD,只將其簡單的總結(jié),有利于在項目中的使用凛篙!
1.在GCD中,個人不需要關(guān)心線程的開辟栏渺!
2.任務(wù)有同步任務(wù)(同步執(zhí)行)和異步任務(wù)(異步執(zhí)行)呛梆,他們之間的區(qū)別是是否會創(chuàng)建新的線程
3.如果是同步(sync)操作,它會阻塞當(dāng)前線程并等待Block中的任務(wù)執(zhí)行完畢磕诊,然后當(dāng)前線程才會繼續(xù)往下運(yùn)行填物。
如果是異步(async)操作,當(dāng)前線程會直接往下執(zhí)行霎终,它不會阻塞當(dāng)前線程滞磺。
4.隊列:用于存放任務(wù)。一共有兩種隊列莱褒, 串行隊列 和 并行隊列击困。
放到串行隊列的任務(wù),GCD 會FIFO(先進(jìn)先出)地取出來一個广凸,執(zhí)行一個阅茶,然后取下一個,這樣一個一個的執(zhí)行谅海;
放到并行隊列的任務(wù)脸哀,GCD 也會FIFO
的取出來,但不同的是扭吁,它取出來一個就會放到別的線程撞蜂,然后再取出來一個又放到另一個的線程。這樣由于取的動作很快侥袜,忽略不計蝌诡,看起來,所有的任務(wù)都是一起執(zhí)行的系馆。不過需要注意送漠,GCD 會根據(jù)系統(tǒng)資源控制并行的數(shù)量,所以如果任務(wù)很多由蘑,它并不會讓所有任務(wù)同時執(zhí)行闽寡。
5.我們用圖表來總結(jié)上述的關(guān)系
同步任務(wù) | 異步任務(wù) | |
---|---|---|
串行隊列 | 當(dāng)前線程,一個一個執(zhí)行 | 其他線程尼酿,一個一個執(zhí)行 |
并行隊列 | 當(dāng)前線程爷狈,一個一個執(zhí)行 | 開很多線程,一起執(zhí)行 |
6.自己可以創(chuàng)建串行隊列, 也可以創(chuàng)建并行隊列裳擎。我們先來看看一個GCD代碼
dispatch_queue_t concurrentQueue = dispatch_queue_create("my.concurrent.queue", DISPATCH_QUEUE_CONCURRENT)
其中第二個參數(shù)是最重要的涎永。第二個參數(shù)用來表示創(chuàng)建的隊列是串行的還是并行的:
傳入DISPATCH_QUEUE_SERIAL
或NULL表示創(chuàng)建串行隊列。
傳入DISPATCH_QUEUE_CONCURRENT
表示創(chuàng)建并行隊列,其中并行隊列有系統(tǒng)定義的四種優(yōu)先級 ,比如DISPATCH_QUEUE_PRIORITY_DEFAULT’
獲取主隊列方法
// 獲取主隊列
dispatch_queue_t mainQueue = dispatch_get_main_queue();
兩者綜合:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^{
[NSThread sleepForTimeInterval:2];
dispatch_async(dispatch_get_main_queue(), ^{
//主線程更新UI
}) ;
});
這是一段我們都非常熟悉的代碼羡微,其中包含著
dispatch_async 是異步任務(wù)
dispatch_get_global_queue 全局隊列
dispatch_get_main_queue 主隊列
DISPATCH_QUEUE_PRIORITY_DEFAULT 創(chuàng)建并行隊列
例子1:
dispatch_queue_t concurrentQueue = dispatch_queue_create("my.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);
NSLog(@“并行隊列上放同步任務(wù)");
dispatch_sync(concurrentQueue, ^(){
NSLog(@"sync - 同步任務(wù)");
[NSThread sleepForTimeInterval:5];
NSLog(@“sync5秒后");
});
NSLog(@“結(jié)束");
輸出 :
GCDTest[] 并行隊列上放同步任務(wù)
GCDTest[] sync - 同步任務(wù)
GCDTest[] ** sync5秒后**//模擬長時間操作
GCDTest[] 結(jié)束
可以見得谷饿,同步任務(wù)要做完Block中的任務(wù),才能繼續(xù)往下執(zhí)行
最常見的使用就是FMDB 中的[queue inDatabase:^(FMDatabase *db)
例子二:
dispatch_queue_t concurrentQueue = dispatch_queue_create("my.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);
NSLog(@"并行隊列上放同步任務(wù)");
dispatch_async(concurrentQueue, ^(){
NSLog(@"async");
[NSThread sleepForTimeInterval:5];
NSLog(@“async5秒后");
});
NSLog(@“結(jié)束”);
輸出:
GCDTest[] 并行隊列上放同步任務(wù)
GCDTest[] 結(jié)束
GCDTest[] async
GCDTest[]** async5秒后**//模擬長時間操作時間
可以見得妈倔,異步任務(wù)不用做完Block中的任務(wù)博投,已經(jīng)開始繼續(xù)往下執(zhí)行
10 barrier
func dispatch_barrier_async(_ queue: dispatch_queue_t, _ block: dispatch_block_t)
:這個方法重點是你傳入的 queue,當(dāng)你傳入的 queue 是通過DISPATCH_QUEUE_CONCURRENT
參數(shù)自己創(chuàng)建的 queue 時盯蝴,這個方法會阻塞這個 queue(注意是阻塞 queue 毅哗,而不是阻塞當(dāng)前線程),一直等到這個 queue 中排在它前面的任務(wù)都執(zhí)行完成后才會開始執(zhí)行自己捧挺,自己執(zhí)行完畢后虑绵,再會取消阻塞,使這個 queue 中排在它后面的任務(wù)繼續(xù)執(zhí)行闽烙。如果你傳入的是其他的 queue, 那么它就和dispatch_async
一樣了翅睛。
func dispatch_barrier_sync(_ queue: dispatch_queue_t, _ block: dispatch_block_t)
:這個方法的使用和上一個一樣,傳入 自定義的并發(fā)隊列(DISPATCH_QUEUE_CONCURRENT)鸣峭,它和上一個方法一樣的阻塞 queue宏所,不同的是 這個方法還會 阻塞當(dāng)前線程。
如果你傳入的是其他的 queue, 那么它就和dispatch_sync
一樣了摊溶。