dispatch_async(dispatch_get_global_queue){
NSLog(@"我在做耗时的操作");
dispatch_sync(dispatch_get_main_queue){
NSLog(@"我回到了主线程更新UI");
}
}
[self.queue addOperationWithBlock:^{
NSLog(@"异步下载图片");
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
NSLog(@"我回到了主线程更新UI");
}];
}];
开启多个任务同时执行。
解决耗时任务在主线程造成的程序卡死的现象
优点:能适当提高程序的执行效率,能适当提供资源的利用率;
缺点:开启的线程越多占据的内存和CPU越多,就会降低程序的执行效率。
进程:系统中正在运行的应用程序。每一个进程之间都是相互独立的,进程在内存中由专用的受保护的内存空间。
线程:线程是进程的基本执行单元,进程中所有的任务都是在线程中执行的。一个进程至少有一个线程。
执行UI刷新事件和点击事件
不要将耗时的操作放到主线程
pthread c语言 线程的生命周期由程序员控制 基本不使用
NSThread oc语言 线程的生命周期由程序员管理 偶尔使用
GCD oc语言 GCD管理线程的生命周期 经常使用
NSOperation oc语言 不用关心线程的生命周期 经常使用,iOS8 之后苹果推荐使用
arc下将c语言的字符串转换成oc字符串!
NSThread *thread=[[NSThread alloc] initWithTarget];
[NSThread detachNewThread…];
[self performSelectorInBackGround…];
创建 -> 就绪 -> 运行 ->阻塞 -> 死亡
name 定位到错误所在的线程
优先级 能调节线程被执行的可能性,不能保证先执行
防止多个线程访问同一个资源
都能解决多线程访问导致的数据安全问题。
互斥锁:遇到锁就等待,呆会再来
自旋锁:遇到锁就在门口等着
自旋锁的执行效率比互斥锁要好
ATP(https)
strong,weak,assign,copy
strong -对象类型
weak delegate,UI控件连线类型
copy 字符串,block
assign 基本数据类型
在主线程的消息循环开启的时候会创建,当消息循环结束的时候就会倾倒自动释放池。
1>循环内部创建大量的临时对象的时候,在循环内部创建自动释放池
2>创建子线程的时候,在线程刚刚开始的位置,创建自动释放池
运行循环就可以简单的理解成,每一个线程开启的一个循环,主线程默认会打开。当有输入事件传入的时候,并且模式匹配的时候就会打开运行循环执行相应的事件。运行循环的目的就是保证程序的不退出,处理输入事件,如果没有事件发生,就让程序进入休眠状态。
输入事件,有两种输入源和定时源。
运行循环常用的几种模式,
任务:需要执行什么操作
队列:用来存放任务
定制任务,将任务添加到队列
队列中分串行队列,并行队列,主队列和全局队列
执行方式: 串行和并行
串行队列
同步执行 不开线程,顺序执行
异步执行 开一个线程,顺序执行
并行队列(全局队列)
同步执行 不开线程,顺序执行
异步执行 开多个线程,无序执行
主队列
同步执行 主线程上执行的话会死锁。
异步执行 主线程,顺序执行
异步的去执行,有相互依赖的操作
主要用在多个异步操作完成之后,对 非线程安全 的对象进行统一更新。适合大规模的 i/o操作。
dispatch_get_global_queue(0,0)数据操作不是在同一个线程中去执行.
dispatch_syn
dispatch_asyn
dispatch_after
dispatch_once_
static id instance = nil;
+ (instancetype)sharedNetworkToolsOnce {
return [[self alloc] init];
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (instance == nil) {
instance = [super allocWithZone:zone];
}
});
return instance;
}
-(id)copyWithZone:(NSZone *)zone
{
return self;
}
dispatch_group_async(dispatch_group_create(), dispatch_get_global_queue(0, 0), ^{ [NSThread sleepForTimeInterval:1.0]; NSLog(@"download A %@", [NSThread currentThread]); });
dispatch_group_notify(dispatch_group_create(), dispatch_get_main_queue(), ^{ NSLog(@"dowload finished %@", [NSThread currentThread]); });
创建操作,把操作添加到队列!!op会自动调用start,main方法!
NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(demo) object:nil];
//队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//把操作添加到队列
[queue addOperation:op];
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{ }];
[op start];
GCD中两个核心的概念。队列和任务,GCD中是怎么实现的。首先是创建队列,然后定制任务。最后是将任务添加至队列。
然后这个里面就有很多概念了。队列中有串行队列,并行队列,主队列,全局队列。其中我们要求重点掌握的就是主队列和全局队列,其实主队列本质上就是一个串行队列,全局队列就是一个并行队列。
任务的话,有同步任务和异步任务。
任务之间的依赖我们可以使用同步任务的方式和barrier(阻塞)来执行。大家想一下还能不能回忆起来。
最后是线程间通讯,不管同步还是异步是不是最后都要回到主队列中去更新数据或者刷新UI显示。是不是dispatch_sync(dispatch_get_main_queue).
然后GCD中还有一些小的知识点就是
主队列,同步执行会出现死锁!这个还有印象吗?怎么产生,相互等待。怎么解决?
GCD中一次性执行代码!有一个非常重要的应用场景就是单例!
另外一个知识点就是延迟操作。Dispatch_after
NSOperation
将操作(异步)添加到队列(全局的并发队列)。
NSOperation的使用是不是更加面象对象。NSOperation是一个抽象的类,我们使用的是他的子类。
首先我们学习了一个摇奖机的小示例程序。那个小示例程序中有一点是需要大家注意的就是取消和暂停都会把正在执行的任务先执行完毕后,才会取消或者暂停队列中的任务。
然后我们还学习了一个最大并发数,GCD中我们能控制线程数吗?不能,GCD中会自动帮我们管理线程。需要注意的就是最大并发数并不是线程数,我们可以通过最大并发数来控制线程数。
NSoperation中也可以实现操作依赖,GCD中实现操作依赖的方式有什么?
同步和阻塞
这个和GCD中有不同的就是NSOperation可以跨队列设置操作间的依赖。。
NSOpeartion控制线程的暂停,取消,记住取消和暂停的都不能取消当前正在执行的任务。
3.写一个异步加载网络图片的小程序
[self.queue addOperationWithBlock:^{
NSLog(@"异步下载图片");
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
NSLog(@"我回到了主线程更新UI");
}];
}];
沙盒默认下有三个目录文件夹 documents,Library,tmp
documents:
一般用来存放应用中建立的文件,如数据库文件,或程序中浏览到的文件数据。如果进行备份会将此文件夹中。
Library
存储应用的默认设置及状态信息
library/cache
用来存放缓存文件,此文件夹下数据在应用退出是不会删除。备份时不会包括
tmp:存放临时文件
[self.imageView sd_setImageWithURL:[NSURL URLWithString:@""] placeholderImage:[UIImage imageNamed:@""]];
SDWebImage
上github,下载demo,查看demo
这个需要自己发挥,能讲出来多少就多少
NSCache是线程安全的,在viewdidReceviedMemory中清除的内存,NSCache不能再次重新添加。可以设置缓存策略!
github地址: https://github.com/FuThD