1、进程与线程
1.1 进程
进程是指在系统中正在运行的一个应用程序
每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内
1.2 线程
1个进程要想执行任务,必须得有线程(每1个进程至少要有1条线程,称为主线程)
一个进程(程序)的所有任务都在线程中执行
1.3 进程和线程的比较
1.线程是CPU调用(执行任务)的最小单位。
2.进程是CPU分配资源的最小单位。
3.一个进程中至少要有一个线程。
4.同一个进程内的线程共享进程的资源。
1.4 多线程原理
同一时间,CPU只能处理1条线程,只有1条线程在工作(执行),多线程并发(同时)执行,其实是CPU快速地在多条线程之间调度(切换),如果CPU调度线程的时间足够快,就造成了多线程并发执行的假象。
那么如果线程非常非常多,会发生什么情况?
CPU会在N多线程之间调度,CPU会累死,消耗大量的CPU资源,同时每条线程被调度执行的频次也会会降低(线程的执行效率降低)。
因此我们一般只开3-5条线程。
1.5 多线程优缺点
多线程的优点
能适当提高程序的执行效率
能适当提高资源利用率(CPU、内存利用率)
多线程的缺点
创建线程是有开销的,iOS下主要成本包括:内核数据结构(大约1KB)、栈空间(子线程512KB、主线程1MB,也可以使用-setStackSize:设置,但必须是4K的倍数,而且最小是16K),创建线程大约需要90毫秒的创建时间
如果开启大量的线程,会降低程序的性能,线程越多,CPU在调度线程上的开销就越大。
程序设计更加复杂:比如线程之间的通信、多线程的数据共享等问题。
1.6 多线程的应用
主线程的主要作用:
显示\刷新UI界面
处理UI事件(比如点击事件、滚动事件、拖拽事件等)
主线程的使用注意:
别将比较耗时的操作放到主线程中
耗时操作会卡住主线程,严重影响UI的流畅度,给用户一种“卡”的坏体验
将耗时操作放在子线程中执行,提高程序的执行效率
1.7多线程实现方案
2、pthread
POSIX线程(POSIX threads),简称Pthreads,是线程的POSIX标准。该标准定义了创建和操纵线程的一整套API。在类Unix操作系统(Unix、Linux、Mac OS X等)中,都使用Pthreads作为操作系统的线程。
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
//创建线程
pthread_t thread;
/*
第一个参数pthread_t *restrict:线程对象
第二个参数const pthread_attr_t *restrict:线程属性
第三个参数void *(*)(void *) :指向函数的指针
第四个参数void *restrict:函数的参数
*/
pthread_create(&thread, NULL,run ,NULL);
}
//void *(*)(void *)
void *run(void *param)
{
for (NSInteger i =0 ; i<10000; i++) {
NSLog(@"%zd--%@-",i,[NSThread currentThread]);
}
return NULL;
}
3、NSTread
3.1 NSTread创建线程方法
// 方法一:创建线程,需要自己开启线程
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
// 开启线程
[thread start];
// 方法二:创建线程后自动启动线程
[NSThread detachNewThreadSelector:@selector(run) toTarget:self withObject:nil];
// 方法三:隐式创建并启动线程
[self performSelectorInBackground:@selector(run) withObject:nil];
//后面两种方法都不用我们开启线程,相对方便快捷,
//但是没有办法拿到子线程对象,没有办法对子线程进行更详细的设置,
//例如线程名字和优先级等。
3.2 NSThread的属性
// 获取当前线程
+ (NSThread *)currentThread;
// 创建启动线程
+ (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)argument;
// 判断是否是多线程
+ (BOOL)isMultiThreaded;
// 线程休眠 NSDate 休眠到什么时候
+ (void)sleepUntilDate:(NSDate *)date;
// 线程休眠时间
+ (void)sleepForTimeInterval:(NSTimeInterval)ti;
// 结束/退出当前线程
+ (void)exit;
// 获取当前线程优先级
+ (double)threadPriority;
// 设置线程优先级 默认为0.5 取值范围为0.0 - 1.0
// 1.0优先级最高
// 设置优先级
+ (BOOL)setThreadPriority:(double)p;
// 获取指定线程的优先级
- (double)threadPriority NS_AVAILABLE(10_6, 4_0);
- (void)setThreadPriority:(double)p NS_AVAILABLE(10_6, 4_0);
// 设置线程的名字
- (void)setName:(NSString *)n NS_AVAILABLE(10_5, 2_0);
- (NSString *)name NS_AVAILABLE(10_5, 2_0);
// 判断指定的线程是否是 主线程
- (BOOL)isMainThread NS_AVAILABLE(10_5,