关于进程和线程:
进程:进程是指在系统中正在运行的一个应用程序
每个进程之间是独立的.
线程:一个进程要想执行任务,必须得有线程(每一个进程中至少要有一个线程),进程只帮你分配内存.
线程是进程的基本执行单元
注:多线程同时执行,其实是CPU快速地在多线程之间调度,同一时间,CPU只能处理一条线程.
主线程:一个iOS程序运行后,默认会开启一条线程,即”主线程”.或”UI线程”
主线程作用:显示/刷新UI界面 处理UI事件
主线程使用注意:别将比较耗时的操作放到主线程中(下载)
线程同步:
1.实质:为了防止多个线程抢夺同一个资源造成的数据安全问题
2.实现:给代码加一个互斥锁(同步锁)
@synchronized(self){
// 被锁住的代码
}
关于GCD:
什么是GCD : 牛逼的中枢调度器,纯C.
优势:GCD是苹果公司为多核的并行运算提出的解决方案
GCD会自动利用更多的CPU内核(双核,四核)
GCD会自动管理线程的生命周期 (创建线程,调度任务,销毁线程)
程序员只需告诉GCD想要执行什任务,不需要编写任何线程管理代码
任务和队列
任务:执行什么操作
队列:用来存放任务
使用就2步骤:
定制任务;
将任务添加到队列中(任务取出遵循FIFO,先进先出 后进后出)
同步与异步
同步: 只能在当前线程中执行任务,不具备开启新线程的能力
异步:可以在新的线程中执行任务,具备开启新线程的能力
我们很多时候会混淆一些术语: 同步 异步 串行 并发
同步和异步主要影响:能不能开启新的线程
并发和串行主要影响:任务的执行方式
并发:多个任务并发(同时)执行
串行:一个任务执行完毕后,再执行下一个任务
// dispatch_sync : 同步,不具备开启线程的能力
// dispatch_async : 异步,具备开启线程的能力
// 并发队列 :多个任务可以同时执行
// 串行队列 :一个任务执行完后,再执行下一个任务
队列:存放任务
全局并发队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
自己创建的串行队列
dispatch_queue_t queue = dispatch_queue_create("cn.yj.queue", NULL);
主队列
dispatch_queue_t queue = dispatch_get_main_queue();
线程间的通信:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 执行耗时的异步操作
dispatch_async(dispatch_get_main_queue(), ^{
//回到主线程,执行UI刷新操作
});
});
- 延时执行
// 3秒后回到主线程执行block中的代码
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), queue, ^{
NSLog(@"------task------%@", [NSThread currentThread]);
});
// 3秒后自动开启新线程 执行block中的代码
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), queue, ^{
NSLog(@"------task------%@", [NSThread currentThread]);
});
- 一次性执行
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSLog(@"----once");
});
- 组队列
如果我们想同时下载两张图片,再合并,可以利用组队列
// 1.队列组
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 2.下载图片1
__block UIImage *image1 = nil;
dispatch_group_async(group, queue, ^{
NSURL *url1 = [NSURL URLWithString:@"http://g.hiphotos.baidu.com/image/pic/item/f2deb48f8c5494ee460de6182ff5e0fe99257e80.jpg"];
NSData *data1 = [NSData dataWithContentsOfURL:url1];
image1 = [UIImage imageWithData:data1];
});
// 3.下载图片2
__block UIImage *image2 = nil;
dispatch_group_async(group, queue, ^{
NSURL *url2 = [NSURL URLWithString:@"http://su.bdimg.com/static/superplus/img/logo_white_ee663702.png"];
NSData *data2 = [NSData dataWithContentsOfURL:url2];
image2 = [UIImage imageWithData:data2];
});
// 4.合并图片 (保证执行完组里面的所有任务之后,再执行notify函数里面的block)
dispatch_group_notify(group, queue, ^{
// 开启一个位图上下文
UIGraphicsBeginImageContextWithOptions(image1.size, NO, 0.0);
// 绘制第1张图片
CGFloat image1W = image1.size.width;
CGFloat image1H = image1.size.height;
[image1 drawInRect:CGRectMake(0, 0, image1W, image1H)];
// 绘制第2张图片
CGFloat image2W = image2.size.width * 0.5;
CGFloat image2H = image2.size.height * 0.5;
CGFloat image2Y = image1H - image2H;
[image2 drawInRect:CGRectMake(0, image2Y, image2W, image2H)];
// 得到上下文中的图片
UIImage *fullImage = UIGraphicsGetImageFromCurrentImageContext();
// 结束上下文
UIGraphicsEndImageContext();
// 5.回到主线程显示图片
dispatch_async(dispatch_get_main_queue(), ^{
self.imageView.image = fullImage;
});
});