一. GCD實(shí)現(xiàn)線程之間的通信
- 需求:
創(chuàng)建全局并發(fā)隊(duì)列, 并且使用異步函數(shù)開啟一條子線程來下載一張圖片
-
當(dāng)圖片下載結(jié)束, 調(diào)用主線程的方法, 將圖片設(shè)置到ImageView中, 刷新UI
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { // 1. 開啟線程下載圖片 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // 2. 創(chuàng)建URL NSURL *url = [NSURL URLWithString:@"http://dimg06.c-ctrip.com/images/tg/161/023/909/de45d234ba8147a0ace4880a92c23994_C_640_640.jpg"]; // 3. 下載二進(jìn)制到本地 NSData *data = [NSData dataWithContentsOfURL:url]; // 4. 將數(shù)據(jù)轉(zhuǎn)換為圖片 UIImage *image = [UIImage imageWithData:data]; NSLog(@"%@", [NSThread currentThread]); // 5. 回到主線程設(shè)置圖片(UI操作切記要在主線程中進(jìn)行, 否則會(huì)出現(xiàn)各種怪異問題) dispatch_async(dispatch_get_main_queue(), ^{ NSLog(@"%@", [NSThread currentThread]); self.imageView.image = image; }); }); }
二. CGD的常用函數(shù)
-
延遲執(zhí)行任務(wù): Delay
- 在開發(fā)中, 會(huì)出現(xiàn)讓一個(gè)方法延遲X秒之后再去執(zhí)行, 稱之為延遲執(zhí)行
- 延遲執(zhí)行的各種方法:
- 使用NSRunLoop的方法, 在當(dāng)前線程中, 推遲X秒, 執(zhí)行指定的方法
[self performSelector:@selector(task) withObject:nil afterDelay:2];
- 使用NSTimer的方法, 在當(dāng)前的運(yùn)行循環(huán)中添加一個(gè)NSTimter的實(shí)例, 當(dāng)X秒后, 執(zhí)行指定的方法
[NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(task) userInfo:nil repeats:NO];
- 使用GCD定時(shí)器, 推遲X秒后執(zhí)行指定的任務(wù)
GCD延遲執(zhí)行, 在原理上是將Block的代碼先保存起來, 然后推遲指定的時(shí)間后, 執(zhí)行Block的代碼
GCD延遲執(zhí)行還可以設(shè)置隊(duì)列, 讓Block的代碼在指定的隊(duì)列中執(zhí)行
-
dispatch_after本身還是一個(gè)異步函數(shù), 因此他可以在指定隊(duì)列的情況下, 使用子線程去執(zhí)行任務(wù), 因此效率更好
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_global_queue(0, 0), ^{ [self task]; NSLog(@"%@", [NSThread currentThread]); });
- 使用NSRunLoop的方法, 在當(dāng)前線程中, 推遲X秒, 執(zhí)行指定的方法
-
一次性代碼(重要!多用于單例!!!)
-
使用格式
static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ [self task]; });
-
注意點(diǎn):
- 一次性代碼在整個(gè)程序中, 僅會(huì)執(zhí)行一次, 當(dāng)再次調(diào)用, dispatch_once函數(shù)中的內(nèi)容將不會(huì)再次執(zhí)行
- 不能再懶加載中使用這個(gè)函數(shù)
- 這個(gè)函數(shù)主要用于創(chuàng)建單例對象, 確保單例在整個(gè)程序中只分配一次內(nèi)存
-
-
柵欄函數(shù)
柵欄函數(shù)用于控制任務(wù)的執(zhí)行順序
在兩個(gè)任務(wù)之間, 增加?xùn)艡诤瘮?shù), 那么任務(wù)的執(zhí)行順序就會(huì)分隔開, 前面的任務(wù)執(zhí)行結(jié)束之后, 后面的任務(wù)才會(huì)執(zhí)行
柵欄函數(shù)主要用于控制并發(fā)隊(duì)列中, 任務(wù)執(zhí)行的順序
在串行隊(duì)列中沒有必要使用柵欄函數(shù), 因?yàn)榇嘘?duì)列本身就是按照順序串行執(zhí)行任務(wù)的
-
注意: 柵欄函數(shù)不能用于全局并發(fā)隊(duì)列, 柵欄函數(shù)在全局并發(fā)并不會(huì)生效
// 3. 柵欄函數(shù) - (void)barrier { // 1. 創(chuàng)建并發(fā)隊(duì)列 dispatch_queue_t queue = dispatch_queue_create("123", DISPATCH_QUEUE_CONCURRENT); // 2. 異步函數(shù)創(chuàng)建任務(wù) dispatch_async(queue, ^{ [self task]; }); dispatch_async(queue, ^{ [self task]; }); // 3. 柵欄函數(shù) dispatch_barrier_async(queue, ^{ NSLog(@"-----------------"); }); dispatch_async(queue, ^{ [self task]; }); dispatch_async(queue, ^{ [self task]; }); dispatch_async(queue, ^{ [self task]; }); }