一、进程和线程的概念与本质以及优缺点
1、进程: 进程指的是系统中运行的一个应用程序,系统中的每个进程都是相互独立的,各自运行在其专用的并且受到保护的内存空间中。
2、线程: 进程中药完成一些任务,而这些任务就是交给线程来管理的,一个进程中至少有一条线程(主线程),也可以有多条线程(子线程),进程中的任何任务都是在线程中执行的。
3、线程的串行:线程中任务的执行是串行的,如果想在线程中执行多个任务,那么只能一个一个按顺序执行,也就是说,子啊同一时刻,线程只能处理一个任务
4、多线程:一个进程中可以开启多条线程,每条线程可以同时执行任务,从而提高了程序的运行效率(优点之一)
5、多线程的原理:其实,在同一时刻,CPU只能处理一条线程,也就是只能执行一条任务,多线程的并发执行,其实是CPU快速的在多个线程之间调度 (切换),因此,如果进程中的线程数太多,会大量消耗cpu资源,线程的切换执行的频次会降低,从而线程的执行效率会大大降低
6、多线程的优点:a. 能够适当的提高程序的执行效率,,提高资源的利用率(CPU、内存的利用率)
缺点: b. 创建线程是有开销的,ios下的开销主要包括栈空间的内存消耗(子线程512KB,主线程1MB,也可以使用-setStackSize来设置线程所占栈空间的大小,但是必须是4K的倍数,而且最小的是16K),创建线程大约需要90毫秒的时间,搜易如果开启大量线程,会降低程序的执行效率, 并且CPU在调度线程上的开销会增大,因为涉及到线程之间的通信 和数据共享问题,所以会增加程序的设计复杂度
二、 IOS中的多线程
1、ios中的主线程: IOS运行一个程序时,会默认开启一条线程,称为“主线程”或者也可以叫做“UI线程”,这条线程的主要任务如下 : a. 显示或者刷新UI
b. 处理UI事件(用户的点击拖拽等事件)
因此,为了有良好的用户交互体验,千万不能将耗时操作放大主线程中来;
2、IOS中实现多线程的方案:
a. pthread c语言 生命周期程序员管理
b. NSThread OC语言 生命周期程序员管理
c. GCD c语言 自行管理生命周期
d. NSOperation oc语言 自行管理生命周期
三、NSThread的使用
1、创建线程方式一:
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];
方式二和方式三开启线程优点:方便快捷
缺点:无法对线程进行详细的设置
2、安全隐患:存在多条线程抢夺同意资源的问题
解决办法:使用互斥锁 格式: @synchronized(锁对象) {//需要锁定的代码}
3、线程之间的通讯实例之一:
-(void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait
四 GCD的使用:
GCD中有2个核心概念
任务:执行什么操作
队列:用来存放任务
将任务添加到队列中,GCD会自动将队列中的任务取出,放到对应的线程中执行
任务的取出遵循队列的FIFO原则:先进先出,后进后出
GCD中有2个用来执行任务的函数
用同步的方式执行任务
dispatch_sync (dispatch_queue_t queue, dispatch_block_t block);
queue:队列
block:任务
用异步的方式执行任务 dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
同步和异步的区别
同步:只能在当前线程中执行任务,不具备开启新线程的能力
异步:可以在新的线程中执行任务,具备开启新线程的能力
GCD的队列可以分为2大类型
并发队列(Concurrent Dispatch Queue)
可以让多个任务并发(同时)执行(自动开启多个线程同时执行任务)
并发功能只有在异步(dispatch_async)函数下才有效
串行队列(Serial Dispatch Queue)
让任务一个接着一个地执行(一个任务执行完毕后,再执行下一个任务)
有4个术语比较容易混淆:同步、异步、并发、串行
同步和异步主要影响:能不能开启新的线程
同步:在当前线程中执行任务,不具备开启新线程的能力
异步:在新的线程中执行任务,具备开启新线程的能力
并发和串行主要影响:任务的执行方式
并发:多个任务并发(同时)执行
串行:一个任务执行完毕后,再执行下一个任务
GCD默认已经提供了全局的并发队列,供整个应用使用,不需要手动创建
使用dispatch_get_global_queue函数获得全局的并发队列
dispatch_queue_t dispatch_get_global_queue(
dispatch_queue_priority_t priority, // 队列的优先级
unsigned long flags); // 此参数暂时无用,用0即可
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); // 获得全局并发队列
线程之间的通讯:
从子线程回到主线程
dispatch_async(
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 执行耗时的异步操作...
dispatch_async(dispatch_get_main_queue(), ^{
// 回到主线程,执行UI刷新操作
});});
其他用法:
iOS常见的延时执行有2种方式
调用NSObject的方法
[self performSelector:@selector(run) withObject:nil afterDelay:2.0];
// 2秒后再调用self的run方法
使用GCD函数
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// 2秒后异步执行这里的代码...
});
单例模式:
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// 只执行1次的代码(这里面默认是线程安全的)
});
需求:
首先:分别异步执行2个耗时的操作
其次:等2个异步操作都执行完毕后,再回到主线程执行操作
如果想要快速高效地实现上述需求,可以考虑用队列组
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 执行1个耗时的异步操作
});
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 执行1个耗时的异步操作
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// 等前面的异步操作都执行完毕后,回到主线程...
});
网友评论