参考文章:http://www.jianshu.com/p/2d57c72016c6
1 开启多线程的方法
- Thread:基于C语言,基本已经不用,需要程序猿开启和管理线程的声明周期
- NSThread:基于Thread的封装,oc语言,需要程序猿开启和管理线程的声明周期
- GCD:旨在替代NSThread,基于C语言,功能强大,自动管理线程的生命周期
- NSOperation:GCD的封装,基于oc语言,自动管理线程的生命周期。
2 GCD的核心概念
- 任务:
同步执行(sync):只能在当前线程中执行任务,不具备开启新线程的能力
异步执行(async):可以在新的线程中执行任务,具备开启新线程的能力 - 队列:
并发队列(Concurrent Dispatch Queue):可以让多个任务并发(同时)执行(自动开启多个线程同时执行任务),并发功能只有在异步(dispatch_async)函数下才有效
串行队列(Serial Dispatch Queue):让任务一个接着一个地执行(一个任务执行完毕后,再执行下一个任务)
3 GCD的基本使用
3.1 线程间通信(子线程下载数据,主线程刷新UI)
//1.开子线程下载图片,异步函数,全局并发队列
dispatch_async(dispatch_get_global_queue(0, 0), ^{
//2.下载图片
//2.1 确定URL
NSURL *url = [NSURL URLWithString:@"https://image.baidu.com"];
//2.2 下载二进制数据
NSData *data = [NSData dataWithContentsOfURL:url];
//2.3 转换为图片
UIImage *image = [UIImage imageWithData:data];
// 子线程
NSLog(@"download---%@",[NSThread currentThread]);
//3.回到主线程刷新UI
// dispatch_async(dispatch_get_main_queue(), ^{
dispatch_sync(dispatch_get_main_queue(), ^{
self.imageView.image = image;
// 主线程
NSLog(@"UI---%@",[NSThread currentThread]);
});
});
3.2 GCD常用函数
(1)时间延迟
//1.NStimer
// NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(task) userInfo:nil repeats:YES];
//2.afterDelay
//[self performSelector:@selector(task) withObject:nil afterDelay:2.0];
//3.GCD
//dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)),queue , ^{
NSLog(@"---GCD----%@",[NSThread currentThread]);
});
(2)一次性代码(注意:不能写在懒加载中)
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSLog(@"---once----");
});
(3)栅栏函数
//栅栏函数:控制并发队列中任务的执行顺序
dispatch_barrier_async(queue, ^{
NSLog(@"+++++++++++++++++++++++++++");
});
(4) 快速迭代函数
//1.获得并发队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//2.快速迭代
/*
第一个参数:要迭代的次数
第二个参数:队列,并发队列
第三个参数:block 封装任务
*/
dispatch_apply(10, queue, ^(size_t index) {
NSLog(@"%zd----%@",index,[NSThread currentThread]);
});
(5) 队列组
//需求:
/*
下载图片1
下载图片2
当下载完成之后合成
*/
-(void)combie
{
//0.创建队列组
dispatch_group_t group = dispatch_group_create();
//1.并发队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//2.异步函数,下载图片1
dispatch_group_async(group, queue, ^{
NSLog(@"DOWNLOAD1---%@",[NSThread currentThread]);
//2.1 确定URL
NSURL *url = [NSURL URLWithString:@"http://imgsrc.baidu.com/forum/pic/item/c69ae2003af33a87ecb1c796c65c10385143b585.jpg"];
//2.2 下载二进制数据
NSData *imageData = [NSData dataWithContentsOfURL:url];
//2.3 转换为图片
self.image1 = [UIImage imageWithData:imageData];
});
//3.异步函数,下载图片2
dispatch_group_async(group, queue, ^{
NSLog(@"DOWNLOAD2---%@",[NSThread currentThread]);
//3.1 确定URL
NSURL *url = [NSURL URLWithString:@"http://s6.sinaimg.cn/middle/6753066ftc67bdde1ca25&690"];
//3.2 下载二进制数据
NSData *imageData = [NSData dataWithContentsOfURL:url];
//3.3 转换为图片
self.image2 = [UIImage imageWithData:imageData];
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"COMBIE---%@",[NSThread currentThread]);
//4.1 开启图形上下文
UIGraphicsBeginImageContext(CGSizeMake(200, 200));
//4.2 画图1
[self.image1 drawInRect:CGRectMake(0, 0, 200, 100)];
//4.3 画图2
[self.image2 drawInRect:CGRectMake(0, 100, 200, 100)];
//4.4 得到图片
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
//4.5 关闭图形上下文
UIGraphicsEndImageContext();
//5.线程间通信,回到主线程属性UI
// dispatch_async(dispatch_get_main_queue(), ^{
self.imageView.image = image;
NSLog(@"UI---%@",[NSThread currentThread]);
//});
});