IOS2

2018-04-02  本文已影响0人  xiaofengl

一、进程和线程:
什么是进程?


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)
特点:不会创建线程
任务执行方式:串行执行

image.png

特殊队列--主队列

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个星期

上一篇下一篇

猜你喜欢

热点阅读