GCD的基本概念
-
1.GCD和NSThread的區(qū)別,GCD不需要程序員管理線程的生命周期,NSThread需要程序員手動(dòng)管理生命周期
-
2.學(xué)習(xí)GCD之前需要先弄清一些概念
-
任務(wù):執(zhí)行什么樣的操作
-
隊(duì)列:用來(lái)存放任務(wù)
-
因?yàn)镚CD不用程序員管理線程的聲明周期,因此可以不管線程的創(chuàng)建和銷(xiāo)毀
-
3.GCD的使用步驟
-
1.定制任務(wù):確認(rèn)想做的事情
-
2.將任務(wù)添加到隊(duì)列中:GCD會(huì)自動(dòng)將隊(duì)列中的任務(wù)取出,放到對(duì)應(yīng)的線程中執(zhí)行
-
任務(wù)的取出遵循隊(duì)列的FIFO原則:先進(jìn)先出,后進(jìn)后出。(這里需要和棧區(qū)分開(kāi)來(lái),棧是先進(jìn)后出,因?yàn)?,棧只有一個(gè)出口)
-
4.GCD中的任務(wù)
-
GCD中有兩個(gè)用來(lái)執(zhí)行任務(wù)的常用函數(shù)
-
同步方式執(zhí)行任務(wù)
- dispatch_sync(dispatch_queue_t _Nonnull queue, <^(void)block>)
-
異步方式執(zhí)行任務(wù)
- dispatch_async(dispatch_queue_t _Nonnull queue, <^(void)block>)
-
同步和異步的區(qū)別
-
同步:只能在當(dāng)前線程中執(zhí)行任務(wù),不具備開(kāi)線程的能力
-
異步:可以在新的線程中執(zhí)行任務(wù),具備開(kāi)啟新線程的能力
-
5.GCD隊(duì)列的類(lèi)型
-
并發(fā)隊(duì)列(Concurrent Dispatch Queue)
-
可以讓多個(gè)任務(wù)并發(fā)(同時(shí))執(zhí)行,自動(dòng)開(kāi)啟多個(gè)線程同時(shí)執(zhí)行任務(wù)
-
并發(fā)功能再有在異步 (dispatch_async)函數(shù)下才有效
-
串行隊(duì)列(Serial Dispatch Queue)
-
讓任務(wù)一個(gè)接著一個(gè)地執(zhí)行,一個(gè)任務(wù)執(zhí)行完畢后,再執(zhí)行下一個(gè)任務(wù)
-
6.GCD任務(wù)和隊(duì)列代碼詳述
@interface ViewController ()
@end
@implementation ViewController
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[self globlQueueAsyncCoucurrent];
}
//異步函數(shù)+串行隊(duì)列:會(huì)開(kāi)線程,開(kāi)一條線程,隊(duì)列中的任務(wù)是串行執(zhí)行
-(void)asyncConcurrent
{
//1.創(chuàng)建隊(duì)列
/**
const char *_Nullable label:C語(yǔ)言字符串,線程的標(biāo)簽
dispatch_queue_attr_t _Nullable attr:隊(duì)列的類(lèi)型
DISPATCH_QUEUE_CONCURRENT:并發(fā)
DISPATCH_QUEUE_SERIAL:串行
*/
dispatch_queue_t asyncQueue = dispatch_queue_create("lxc", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(asyncQueue, ^{
NSLog(@"queue1---%@",[NSThread currentThread]);
});
//2.封裝任務(wù)->添加任務(wù)到隊(duì)列中
/**
dispatch_queue_t queue:隊(duì)列是哪個(gè)
dispatch_block_t block:block參數(shù)
*/
dispatch_async(asyncQueue, ^{
NSLog(@"queue2---%@",[NSThread currentThread]);
});
dispatch_async(asyncQueue, ^{
NSLog(@"queue3---%@",[NSThread currentThread]);
});
dispatch_async(asyncQueue, ^{
NSLog(@"queue4---%@",[NSThread currentThread]);
});
NSLog(@"----end----");
//線程沒(méi)有順序
}
//異步函數(shù)+串行隊(duì)列:會(huì)一條開(kāi)線程,隊(duì)列中的任務(wù)是串行執(zhí)行
-(void)asyncSerial
{
dispatch_queue_t asyncQueue = dispatch_queue_create("cyf", DISPATCH_QUEUE_SERIAL);
dispatch_async(asyncQueue, ^{
NSLog(@"queue1---%@",[NSThread currentThread]);
});
dispatch_async(asyncQueue, ^{
NSLog(@"queue2---%@",[NSThread currentThread]);
});
dispatch_async(asyncQueue, ^{
NSLog(@"queue3---%@",[NSThread currentThread]);
});
dispatch_async(asyncQueue, ^{
NSLog(@"queue4---%@",[NSThread currentThread]);
});
NSLog(@"----end----");
}
//同步函數(shù)+并行隊(duì)列:不會(huì)開(kāi)啟線程,所有任務(wù)都在主線程中執(zhí)行,隊(duì)列中的任務(wù)是并行執(zhí)行
-(void)syncConcurent
{
dispatch_queue_t syncQueue = dispatch_queue_create("23", DISPATCH_QUEUE_CONCURRENT);
dispatch_sync(syncQueue, ^{
NSLog(@"syncQueue1----%@",[NSThread currentThread]);
});
dispatch_sync(syncQueue, ^{
NSLog(@"syncQueue2----%@",[NSThread currentThread]);
});
dispatch_sync(syncQueue, ^{
NSLog(@"syncQueue3----%@",[NSThread currentThread]);
});
dispatch_sync(syncQueue, ^{
NSLog(@"syncQueue4----%@",[NSThread currentThread]);
});
}
//同步函數(shù)+串行隊(duì)列:不會(huì)開(kāi)啟線程,所有的任務(wù)都在主線程中執(zhí)行,隊(duì)列中的任務(wù)是串行執(zhí)行
-(void)syncSerial
{
dispatch_queue_t syncQueue = dispatch_queue_create("22", DISPATCH_QUEUE_SERIAL);
dispatch_sync(syncQueue, ^{
NSLog(@"syncQueue1----%@",[NSThread currentThread]);
});
dispatch_sync(syncQueue, ^{
NSLog(@"syncQueue2----%@",[NSThread currentThread]);
});
dispatch_sync(syncQueue, ^{
NSLog(@"syncQueue3----%@",[NSThread currentThread]);
});
dispatch_sync(syncQueue, ^{
NSLog(@"syncQueue4----%@",[NSThread currentThread]);
});
NSLog(@"---end---");
}
//全局并發(fā)隊(duì)列+并發(fā):不會(huì)創(chuàng)建線程,會(huì)從GCD本身就有全局并發(fā)隊(duì)列,只是拿出,并且創(chuàng)建多少線程不受控制
-(void)globlQueueAsyncCoucurrent
{
/*
//獲得全局并發(fā)隊(duì)列:
第一個(gè)參數(shù):隊(duì)列的優(yōu)先級(jí)
DISPATCH_QUEUE_PRIORITY_DEFAULT 默認(rèn) 0
DISPATCH_QUEUE_PRIORITY_HIGH 最高 2
DISPATCH_QUEUE_PRIORITY_BACKGROUND 最低優(yōu)先級(jí) -1
DISPATCH_QUEUE_PRIORITY_LOW 低優(yōu)先級(jí) 1
第二個(gè)參數(shù):傳0即可
*/
//獲得全局并發(fā)隊(duì)列,這個(gè)隊(duì)列本身是存在的,在GCD中本身就有全局并發(fā)隊(duì)列,只是拿過(guò)來(lái)用一下,需要注意的是全局并發(fā)隊(duì)列,是不受控制的,并不是有多少任務(wù)就先多少線程
dispatch_queue_t globlQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(globlQueue, ^{
NSLog(@"asyncQueue1----%@",[NSThread currentThread]);
});
dispatch_async(globlQueue, ^{
NSLog(@"asyncQueue2----%@",[NSThread currentThread]);
});
dispatch_async(globlQueue, ^{
NSLog(@"asyncQueue3----%@",[NSThread currentThread]);
});
dispatch_async(globlQueue, ^{
NSLog(@"asyncQueue4----%@",[NSThread currentThread]);
});
//全局并發(fā)隊(duì)列沒(méi)有順序
}
@end
dispatch_queue_t queue = dispatch_get_global_queue(0,0);
/**
* @param DISPATCH_TIME_NOW 從現(xiàn)在開(kāi)始計(jì)算時(shí)間
* @param int64_t 延遲的時(shí)間 2.0 GCD時(shí)間單位:納秒
* @dispatch_get_main_queue 隊(duì)列
CGD的定時(shí)任務(wù)可以控制幾秒后再那個(gè)線程中執(zhí)行
*/
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), queue, ^{
NSLog(@"-----GCD------%@",[NSThread currentThread]);
});
//一次性代碼
//不能放在懶加載中的,應(yīng)用場(chǎng)景:單例模式
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSLog(@"---once----");
});
- ##### 柵欄函數(shù)
dispatch_queue_t queue = dispatch_queue_create("download", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSLog(@"download1-----%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"download2-----%@",[NSThread currentThread]);
});
/**
* GCD柵欄函數(shù)
該函數(shù)可以控制多線程異步的執(zhí)行順序(哪個(gè)先執(zhí)行哪個(gè)后執(zhí)行)
注意:在使用柵欄函數(shù)的時(shí)候不可以使用全局并發(fā)隊(duì)列
*/
dispatch_barrier_async(queue, ^{
NSLog(@"+++++++++++++++");
});
dispatch_async(queue, ^{
NSLog(@"download4-----%@",[NSThread currentThread]);
});
@param 10 迭代的次數(shù)
@param 隊(duì)列(并發(fā)隊(duì)列)
@param index 索引
@return
dispatch_apply(10, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t index) {
NSLog(@"%zd-----%@",index,[NSThread currentThread]);
-
GCD隊(duì)列組函數(shù)
- 隊(duì)列組
- 如果有這么一種需求,首先分別異步執(zhí)行2個(gè)耗時(shí)操作,其次等2個(gè)異步操作都執(zhí)行完畢后,再回到主線程執(zhí)行操作。如果遇到這種業(yè)務(wù)可以考慮用隊(duì)列組實(shí)現(xiàn)
//1.創(chuàng)建隊(duì)列
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
//2.創(chuàng)建隊(duì)列組
dispatch_group_t group = dispatch_group_create();
//3.隊(duì)列組函數(shù)
/**
1.封裝任務(wù)
2.把任務(wù)添加到隊(duì)列中
3.會(huì)監(jiān)聽(tīng)任務(wù)的執(zhí)行情況,通知group
*/
dispatch_group_async(group, queue, ^{
NSLog(@"1----%@",[NSThread currentThread]);
});
dispatch_group_async(group, queue, ^{
NSLog(@"2----%@",[NSThread currentThread]);
});
dispatch_group_async(group, queue, ^{
NSLog(@"3----%@",[NSThread currentThread]);
});
//監(jiān)聽(tīng)通知,當(dāng)隊(duì)列組中所有的任務(wù)都執(zhí)行完畢的時(shí)候,進(jìn)入到下面的方法
/**
* 監(jiān)聽(tīng)通知的時(shí)候函數(shù)不會(huì)阻塞,內(nèi)部本身是異步的
*/
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"end---%@",[NSThread currentThread]);
});
/**
監(jiān)聽(tīng)通知的另一個(gè)函數(shù),這個(gè)函數(shù)會(huì)一直等待,死等。直到隊(duì)列組中所有的任務(wù)都執(zhí)行完畢之后才能執(zhí)行,內(nèi)部本身是同步的
*/
dispatch_group_wait(group, DISPATCH_TIME_NOW);
NSLog(@"----end----");