IOS2
一、进程和线程:
什么是进程?
3.png
什么是线程?
4.png
多线程原理?
5.png
二、多线程
iOS中多线程实现方案:
2.jpg
1.pthread 几乎不用,可自行了解
2.NSThread
一个NSThread对象就代表一条线程
创建线程的方式:
1.创建线程后,启动
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
thread.name = @"设置线程的名字"; // 这里可以设置线程的名字,可用于方便调试等功能
[thread start]; // 启动线程
// 线程一启动,就会在线程thread中执行self的run方法
2.创建线程后自动启动线程
[NSThread detachNewThreadSelector:@selector(run) toTarget:self withObject:nil];
3.隐式创建并启动线程
[self performSelectorInBackground:@selector(run) withObject:nil]; // 这样创建的是子线程
[self performSelector:@selector(run) withObject:nil]; // 这样创建的是主线程,其实是相当于[self run];这个方法了。
上述2种创建线程方式相对于1的优缺点
优点:简单快捷
缺点:无法对线程进行更详细的设置
线程的状态:
第1行:NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
第2行:[thread start];
6.png
说明:
第1行代码执行完后,就会创建一个线程对象,所以内存中,会有一个线程对象,注意,此时还没有放进可调度的线程池,此时线程处于新建状态。
第2行代码执行,开始线程,一旦开始线程,默认会放进一个可调度的线程池,供线程池来回切换、调度。此时线程处于能运行的状态,就是就绪(Runnable)状态,即能运行状态,能被调度状态,但并不代表已经运行。平常之所以执行start后,就调用我们定义的方法(这里是run),是因为CPU处理非常快,我们感觉不到还有就绪(Runnable)这个过程的而已。
我们知道,CPU同一时间,只能处理一个线程。之所以有多线程,只不过是CPU快速的来回切换不同的线程,造成的假象而已。
此时CPU调度了当前线程(橙色背景的线程),此时线程的状态才是运行状态(running),那么假如,CPU调度了其他线程对象(红色背景的线程),那么橙色背景线程又处于就绪状态(Runnable)了。所以线程就处于就绪跟运行状态来回切换了。
一旦橙色背景线程处于睡眠、同步锁状态时,就是阻塞状态,那么它就会从可调度线程池移除,注意,只是在可调度线程池移除,仍然在内存中的。
一旦睡眠到到时、得到同步锁,那么线程就会又回到可调度线程池,又处于就绪状态了。
线程任务执行完毕、异常、强制退出,那么这个线程就会死亡了。
线程安全:
1.png
说明:有2条线程卖票,同时读到还剩1000张票,但是等最后这2条线程执行完毕后,还剩999张票。这样就有问题了。本来应该是998的。
解决办法:加锁
3.png
使用互斥锁的前提:多条线程抢夺同一份资源。
iOS如何做到线程同步?使用加锁。
线程同步:多条线程在同一条线上执行(按顺序的执行任务)。
OC在定义属性时有nonatomic和atomic两种选择
atomic:原子属性,为setter方法加锁(默认就是atomic)
nonatomic:非原子属性,不会为setter方法加锁
nonatomic和atomic对比
atomic:线程安全,需要消耗大量的资源
nonatomic:非线程安全,适合内存小的移动设备
iOS开发的建议
所有属性都声明为nonatomic
尽量避免多线程抢夺同一块资源
尽量将加锁、资源抢夺的业务逻辑交给服务器端处理,减小移动客户端的压力
3.GCD
理解:将任务添加到队列中去执行。
GCD的队列可以分为2大类型
并发队列(Concurrent Dispatch Queue)
可以让多个任务并发(同时)执行(自动开启多个线程同时执行任务)
并发功能只有在异步(dispatch_async)函数下才有效
串行队列(Serial Dispatch Queue)
让任务一个接着一个地执行(一个任务执行完毕后,再执行下一个任务)
GCD的使用就2个步骤
1.定制任务
确定想做的事情
2.将任务添加到队列中
GCD会自动将队列中的任务取出,放到对应的线程中执行
任务的取出遵循队列的FIFO原则:先进先出,后进后出
有4个术语比较容易混淆:同步、异步、并发、串行
同步和异步主要影响:能不能开启新的线程
同步:在当前线程中执行任务,不具备开启新线程的能力
异步:在新的线程中执行任务,具备开启新线程的能力
并发和串行主要影响:任务的执行方式
并发:多个任务并发(同时)执行
串行:一个任务执行完毕后,再执行下一个任务
GCD默认已经提供了全局的并发队列,供整个应用使用,不需要手动创建
使用dispatch_get_global_queue函数获得 全局 的 并发 队列
因此,有4种组合的:
1.异步并发队列(async)-------最常用
特点:会创建多条线程
任务执行方式:并发执行
image.png
2.异步串行队列(async)(有时候用)
特点:会创建子线程,但是只会开一条线程
任务执行方式:串行执行(一个任务执行完毕后,再执行一个)
image.png
3.同步并发队列(sync)
特点:不会创建子线程
任务执行方式:串行执行
并发队列失去了并发功能
image.png
4.同步串行队列(sync)
特点:不会创建线程
任务执行方式:串行执行
特殊队列--主队列
5.异步--主队列
特点:异步功能失效,不会开线程了
原因:添加到主队列中的任务,都会自动放到主线程中去执行
image.png
6.同步--主队列
特点:会卡死,不能这样使用
image.png
如图:
image.png
获得串行队列有2中方式:
1.创建串行队列
dispatch_queue_t queue = dispatch_queue_create("cn.itcast.queue", NULL); // 创建
2.使用主队列
dispatch_queue_t queue = dispatch_get_main_queue();
各队列的执行效果:
image.png
队列组:dispatch_group
image.png
4、NSOperation
image.png image.png image.png
依赖的使用:
image.png
SDWebImage的原理,防止Cell图片下载
image.png
SDWebImage的默认缓存时长是多少?---1个星期