GCD 簡介
什么是GCD?
全稱是 Grand Central Dispatch 純 C 語言具篇,提供了非常多強大的函數(shù)
GCD的優(yōu)勢
GCD 是蘋果公司為多核的并行運算提出的解決方案
GCD 會自動利用更多的CPU內(nèi)核(比如雙核苍日、四核)
GCD 會自動管理線程的生命周期(創(chuàng)建線程维费、調(diào)度任務(wù)讼撒、銷毀線程) 程序員只需要告訴 GCD 想要執(zhí)行什么任務(wù),不需要編寫任何線程管理代碼
任務(wù)使用 block 封裝
任務(wù)的 block 沒有參數(shù)也沒有返回值
執(zhí)行任務(wù)的函數(shù)
異步
dispatch_async
不用等待當前語句執(zhí)行完畢充岛,就可以執(zhí)行下一條語句
會開啟線程執(zhí)行 block 的任務(wù)
異步是多線程的代名詞
同步
dispatch_sync
必須等待當前語句執(zhí)行完畢敦姻,才會執(zhí)行下一條語句
不會開啟線程
在當前執(zhí)行 block 的任務(wù)
主隊列
專?用來在主線程上調(diào)度任務(wù)的串行隊列
不會開啟線程
如果當前主線程正在有任務(wù)執(zhí)行,那么無論主隊列中當前被添加了什么任務(wù)铐刘,都不會被調(diào)度dispatch_get_main_queue();
全局并發(fā)隊列
為了方便程序員的使用陪每,蘋果提供了全局隊列 dispatch_get_global_queue(0, 0)
全局隊列是一個并發(fā)隊列
在使用多線程開發(fā)時,如果對隊列沒有特殊需求,在執(zhí)行異步任務(wù)時奶稠,可以直接使用全局隊 列
柵欄函數(shù)
最直接的作用: 控制任務(wù)執(zhí)行順序,同步
dispatch_barrier_async 前面的任務(wù)執(zhí)行完畢才會來到這里
dispatch_barrier_sync 作用相同,但是這個會堵塞線程,影響后面的任務(wù)執(zhí)行
非常重要的一點: 柵欄函數(shù)只能控制同一并發(fā)隊列
調(diào)度組
最直接的作用: 控制任務(wù)執(zhí)行順序
dispatch_group_create 創(chuàng)建組
dispatch_group_async 進組任務(wù)
dispatch_group_notify 進組任務(wù)執(zhí)行完畢通知
dispatch_group_wait 進組任務(wù)執(zhí)行等待時間
dispatch_group_enter 進組
dispatch_group_leave 出組
注意搭配使用
信號量dispatch_semaphore_t
dispatch_semaphore_create 創(chuàng)建信號量
dispatch_semaphore_wait 信號量等待
dispatch_semaphore_signal 信號量釋放
同步->當鎖, 控制GCD最大并發(fā)數(shù)
/**
主隊列同步
不會開線程
*/
- (void)mainSyncTest{
NSLog(@"0");
// 等
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"1");
});
NSLog(@"2");
}
/**
主隊列異步
不會開線程 順序
*/
- (void)mainAsyncTest{
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"1");
});
NSLog(@"2");
}
/**
全局異步
全局隊列:一個并發(fā)隊列
*/
- (void)globalAsyncTest{
for (int i = 0; i<20; i++) {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"%d-%@",i,[NSThread currentThread]);
});
}
NSLog(@"hello queue");
}
/**
全局同步
全局隊列:一個并發(fā)隊列
*/
- (void)globalSyncTest{
for (int i = 0; i<20; i++) {
dispatch_sync(dispatch_get_global_queue(0, 0), ^{
NSLog(@"%d-%@",i,[NSThread currentThread]);
});
}
NSLog(@"hello queue");
}
/**
同步并發(fā) : 堵塞 同步鎖 隊列 : resume supend 線程 操作, 隊列掛起 任務(wù)能否執(zhí)行
*/
- (void)concurrentSyncTest{
//1:創(chuàng)建并發(fā)隊列
dispatch_queue_t queue = dispatch_queue_create("Cooci", DISPATCH_QUEUE_CONCURRENT);
for (int i = 0; i<20; i++) {
dispatch_sync(queue, ^{
NSLog(@"%d-%@",i,[NSThread currentThread]);
});
}
NSLog(@"hello queue");
}
/**
異步并發(fā): 有了異步函數(shù)不一定開辟線程
*/
- (void)concurrentAsyncTest{
//1:創(chuàng)建并發(fā)隊列
dispatch_queue_t queue = dispatch_queue_create("Cooci", DISPATCH_QUEUE_CONCURRENT);
for (int i = 0; i<100; i++) {
dispatch_async(queue, ^{
NSLog(@"%d-%@",i,[NSThread currentThread]);
});
}
NSLog(@"hello queue");
}
/**
串行異步隊列
*/
- (void)serialAsyncTest{
//1:創(chuàng)建串行隊列
dispatch_queue_t queue = dispatch_queue_create("Cooci", DISPATCH_QUEUE_SERIAL);
for (int i = 0; i<20; i++) {
dispatch_async(queue, ^{
NSLog(@"%d-%@",i,[NSThread currentThread]);
});
}
NSLog(@"hello queue");
}
/**
串行同步隊列 : FIFO: 先進先出
*/
- (void)serialSyncTest{
//1:創(chuàng)建串行隊列
dispatch_queue_t queue = dispatch_queue_create("Cooci", DISPATCH_QUEUE_SERIAL);
for (int i = 0; i<20; i++) {
dispatch_sync(queue, ^{
NSLog(@"%d-%@",i,[NSThread currentThread]);
});
}
}
/**
* 還原最基礎(chǔ)的寫法,很重要
*/
- (void)syncTest{
dispatch_block_t block = ^{
NSLog(@"hello GCD");
};
//串行隊列
dispatch_queue_t queue = dispatch_queue_create("com.lg.cn", NULL);
// 函數(shù)
dispatch_async(queue, block);
}
#import "KCImageManger.h"
// 保存在常量區(qū)
static id instance;
@implementation KCImageManger
/**
每次類初始化的時候進行調(diào)用
1俯艰、+load它不遵循那套繼承規(guī)則。如果某個類本身沒有實現(xiàn)+load方法锌订,那么不管其它各級超類是否實現(xiàn)此方法竹握,系統(tǒng)都不會調(diào)用。+load方法調(diào)用順序是:SuperClass -->SubClass --> CategaryClass辆飘。
3啦辐、+initialize是在類或者它的子類接受第一條消息前被調(diào)用,但是在它的超類接收到initialize之后蜈项。也就是說+initialize是以懶加載的方式被調(diào)用的芹关,如果程序一直沒有給某個類或它的子類發(fā)送消息,那么這個類的+initialize方法是不會被調(diào)用的紧卒。
4侥衬、只有執(zhí)行+initialize的那個線程可以操作類或類實例,其他線程都要阻塞等著+initialize執(zhí)行完跑芳。
5轴总、+initialize 本身類的調(diào)用都會執(zhí)行父類和分類實現(xiàn) initialize方法都會被調(diào)多次
*/
+ (void)initialize{
NSLog(@"父類");
if (instance == nil) {
instance = [[self alloc] init];
}
}
/**
配合上面 也能進行單利
*/
+ (instancetype)manager{
return instance;
}
/**
* 所有為類的對象分配空間的方法,最終都會調(diào)用到 allovWithZone 方法
* 下面這樣的操作相當于鎖死 該類的所有初始化方法
*/
+(instancetype)allocWithZone:(struct _NSZone *)zone{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [super allocWithZone:zone];
});
return instance;
}
/**
單利
*/
+(instancetype)shareManager{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[self alloc] init];
});
return instance;
}
@end
/**
模糊圖片
@param sourceImage 源圖
@return 返回結(jié)果圖片
*/
+ (UIImage *)kc_filterImage:(UIImage *)sourceImage{
if (!sourceImage) {
sourceImage = [UIImage imageNamed:@"backImage"];
}
CIContext *context = [CIContext contextWithOptions:nil];
CIImage *image = [[CIImage alloc] initWithImage:sourceImage];
CIFilter *filter = [CIFilter filterWithName:@"CIGaussianBlur"];
[filter setValue:image forKey:kCIInputImageKey];
[filter setValue:@10.0f forKey:@"inputRadius"];
CIImage *result = [filter valueForKey:kCIOutputImageKey];
CGImageRef outImage = [context createCGImage:result fromRect:[result extent]];
UIImage *bluerImage = [UIImage imageWithCGImage:outImage];
return bluerImage;
}
/**
給指定圖片加文字水印
@param text 文字
@param backImage 背景圖片
@return 返回文字水印照片
*/
+ (UIImage *)kc_WaterImageWithText:(NSString *)text backImage:(UIImage *)backImage{
if (!backImage) {
backImage = [UIImage imageNamed:@"backImage"];
}
NSDictionary *attDict = @{NSFontAttributeName:[UIFont systemFontOfSize:40],NSForegroundColorAttributeName:[UIColor whiteColor]};
return [self kc_WaterImageWithImage:backImage text:text textPoint:CGPointZero attributedString:attDict];
}
// 給圖片添加文字水硬└觥:
+ (UIImage *)kc_WaterImageWithImage:(UIImage *)image text:(NSString *)text textPoint:(CGPoint)point attributedString:(NSDictionary * )attributed{
//1.開啟上下文
UIGraphicsBeginImageContextWithOptions(image.size, NO, 0);
//2.繪制圖片
[image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)];
//添加水印文字
[text drawAtPoint:point withAttributes:attributed];
//3.從上下文中獲取新圖片
UIImage * newImage = UIGraphicsGetImageFromCurrentImageContext();
//4.關(guān)閉圖形上下文
UIGraphicsEndImageContext();
//返回圖片
return newImage;
}
/**
給指定圖片加圖片水印
@param waterImage 水印圖片
@param rect 位置
@return 返回圖片水印照片
*/
+ (UIImage *)kc_WaterImageWithWaterImage:(UIImage *)waterImage backImage:(UIImage *)backImage waterImageRect:(CGRect)rect{
UIImage *newBackImage = backImage;
if (!newBackImage) {
newBackImage = [UIImage imageNamed:@"backImage"];
}
return [self kc_WaterImageWithImage:newBackImage waterImage:waterImage waterImageRect:rect];
}
// 給圖片添加圖片水印
+ (UIImage *)kc_WaterImageWithImage:(UIImage *)image waterImage:(UIImage *)waterImage waterImageRect:(CGRect)rect{
//1.獲取圖片
//2.開啟上下文
UIGraphicsBeginImageContextWithOptions(image.size, NO, 0);
//3.繪制背景圖片
[image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)];
//繪制水印圖片到當前上下文
[waterImage drawInRect:rect];
//4.從上下文中獲取新圖片
UIImage * newImage = UIGraphicsGetImageFromCurrentImageContext();
//5.關(guān)閉圖形上下文
UIGraphicsEndImageContext();
//返回圖片
return newImage;
}