GCD
简介
- 1.旨在代替NSThread等线程技术
- 2.能够充分利用多核的特点
- 3.用到的两个核心概念:队列(并发+串行)+任务(同步+异步)
- 有一点需要注意:异步函数具有开启线程的能力,而同步函数不会开启线程
基本使用
- 01 异步函数+并发队列:开启多条线程,并发执行任务(最常用)
- 02 异步函数+串行队列:开启一条线程,串行执行任务
- 03 同步函数+并发队列:不开线程,在当前线程里串行执行任务
- 04 同步函数+串行队列:不开线程,在当前线程里串行执行任务
- 05 异步函数+主队列:不开线程,在主线程中串行执行任务
- 06 同步函数+主队列:不开线程,串行执行任务(注意死锁发生)
常用代码示例:
- 1.异步+并发
//异步+并发(创建多个线程,并发执行)
-(void)asyncConcurrent{
/*
第一个参数:C语言的字符串 给队列起一个名字
第二个参数:类型
DISPATCH_QUEUE_CONCURRENT 并发队列
DISPATCH_QUEUE_SERIAL 串行队列
*/
//创建并发队列
dispatch_queue_t queue=dispatch_queue_create("wujian.com.con", DISPATCH_QUEUE_CONCURRENT);
//封装任务并把任务添加到队列当中
dispatch_async(queue, ^{
NSLog(@"1--------------%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"2--------------%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"3--------------%@",[NSThread currentThread]);
});
}
- 2.异步+串行
-(void)asyncSerial{
NSLog(@"开始---");
dispatch_queue_t queue=dispatch_queue_create("lslslslsll.com", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
NSLog(@"1--------------%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"2--------------%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"3--------------%@",[NSThread currentThread]);
});
NSLog(@"结束---");
}
注意:此处运行会发现先打印“开始--”,然后打印“结束--”,在这之后再处理这两者中间的具体任务,这其实是异步函数的一个特点,异步函数采用的是回调的机制,像打印这种简单的操作,就直接执行了,而对于异步函数里的任务,在其他操作完成之后再去执行,这样做会防止死锁的发生。
- 3.同步+串行(在当前线程中串行执行)
-(void)syncSerial{
dispatch_queue_t queue=dispatch_queue_create("com.sssss", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue, ^{
NSLog(@"1--------------%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"2--------------%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"3--------------%@",[NSThread currentThread]);
});
}
- 4.同步+并发(不会创建线程,在当前线程中串行执行)
-(void)syncConcurrent{
//自己创建的并发队列
// dispatch_queue_t queue=dispatch_queue_create("ldsjfl.com", DISPATCH_QUEUE_CONCURRENT);
//获取全局队列(用法与上面几乎无异)
dispatch_queue_t queue=dispatch_get_global_queue(0, 0);
dispatch_sync(queue, ^{
NSLog(@"1--------------%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"2--------------%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"3--------------%@",[NSThread currentThread]);
});
}
- 5.异步+主队列(与主线程相关):在主线程中串行执行,由于异步的执行特点,所以不会造成死锁
-(void)asyncMainQueue{
dispatch_queue_t queue=dispatch_get_main_queue();
dispatch_async(queue, ^{
NSLog(@"1--------------%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"2--------------%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"3--------------%@",[NSThread currentThread]);
});
}
- 6.同步+主队列:会造成死锁(在子线程中不会有死锁发生)
- 如果主队列中有任务,那么主队列会安排主线程来执行当前队列中的任务,但是在调度之前会先检查主线程的状态,如果主线程在忙那么就暂停调度队列中的任务,等到主线程空闲的时候再调度(而此处的主线程刚好在执行自身这个函数) (只有主队列关心主线程忙不忙)
-(void)syncMainQueue{
NSLog(@"ssss");
dispatch_queue_t queue=dispatch_get_main_queue();
dispatch_sync(queue, ^{
NSLog(@"1--------------%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"2--------------%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"3--------------%@",[NSThread currentThread]);
});
}
获得串行队列的两种途径
- 1.通过函数自己创建
dispatch_queue_t queue=dispatch_queue_create("lslslslsll.com", DISPATCH_QUEUE_SERIAL);
- 2.获得系统的主队列
dispatch_queue_t queue=dispatch_get_main_queue();
获得全局队列的两种途径
- 1.通过函数自己创建
dispatch_queue_t queue=dispatch_queue_create("wujian.com.con", DISPATCH_QUEUE_CONCURRENT);
- 2.获得系统的全局队列(建议使用这种方法)
//第一个参数是队列的优先级,可以传0表示默认,第二个参数暂时用不上,是苹果预留的参数,传0即可。
dispatch_queue_t queue=dispatch_get_global_queue(0, 0);
GCD中的线程通信
- (void)viewDidLoad {
[super viewDidLoad];
//开子线程
//01 获得全局并发队列
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
//02 使用异步函数+并发队列
dispatch_async(queue, ^{
//03 确定URL
NSURL *url = [NSURL URLWithString:@"http://XXXXX.jpg"];
//04 把图片的二进制数据下载到本地
NSData *data = [NSData dataWithContentsOfURL:url];
//05 转换格式
UIImage *image = [UIImage imageWithData:data];
NSLog(@"耗时操作---%@",[NSThread currentThread]);
//06 显示图片(回到主线程,其实是一种嵌套的模式)
dispatch_async(dispatch_get_main_queue(), ^{
self.imageView.image = image;
NSLog(@"UI操作---%@",[NSThread currentThread]);
});
});
}