谈到多线程就到说到线程和进程,就要说到NSThread、GCD、NSOperation!
基本知识
1. 进程(process)
进程是指在系统中正在运行的一个应用程序,就是一段程序的执行过程。
每个进程之间是相互独立的, 每个进程均运行在其专用且受保护的内存空间内。
进程是一个具有一定独立功能的程序关于某次数据集合的一次运行活动,它是操作系统分配资源的基本单元。
进程状态:进程有三个状态,就绪,运行和阻塞。就绪状态其实就是获取了除cpu外的所有资源,只要处理器分配资源马上就可以运行。运行态就是获取了处理器分配的资源,程序开始执行,阻塞态,当程序条件不够时,需要等待条件满足时候才能执行,如等待I/O操作的时候,此刻的状态就叫阻塞态。
2. 线程(thread)
一个进程要想执行任务,必须要有线程,至少有一条线程
一个进程的所有任务都是在线程中执行
每个应用程序想要跑起来,最少也要有一条线程存在,其实应用程序启动的时候我们的系统就会默认帮我们的应用程序开启一条线程,这条线程也叫做'主线程',或者'UI线程'
3. 进程和线程的关系
线程是进程的执行单元,进程的所有任务都在线程中执行!
线程是 CPU 调用的最小单位
进程是 CPU 分配资源和调度的单位
一个程序可以对应多个进程,一个进程中可有多个线程,但至少要有一条线程
同一个进程内的线程共享进程资源
举个例子:进程就好比公司中的一个个部门,线程则代表着部门中的同事,而主线程当然是我们的老板了,一个公司不能没有老板,一个程序不能没有线程其实都是一个道理.
相同点:进程和线程都是有操作系统所提供的程序运行的基本单元,系统利用该基本单元实现系统对应用程序的并发性。
不同点:
进程和线程的主要差别在于他们是不同的操作系统资源管理方式。
进程有独立的地址空间,一个进程crash后,在保护模式下不会对其他进程产生影响。
而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间。一个线程crash就等于整个进程crash
多进程的程序比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。
优缺点:
进程执行开销大,但利于资源的管理和保护。
线程执行开销小,但不利于资源的管理和保护。线程适合于在SMP(多核处理机)机器上运行。
4. 多线程
Mac、iPhone的操作系统OS X、iOS根据用户的指示启动应用程序后,首先便将包含在应用程序中的CPU命令列配置到内存中。CPU从应用程序知道的地址开始,一个一个执行CPU命令列。
在OC的if或for语句等控制语句或函数调用的情况下,执行命令列的地址会远离当前的位置(位置迁移)。但是,由于一个CPU一次只能执行一个命令,不能执行某处分开的并列的两个命令,因此通过CPU执行的CPU命令列就好比一条无分叉的大道,其执行不会出现分歧。
这里所说的“1个CPU执行的CPU命令列为一条无分叉路径”,即为“线程”
这种无分叉路径不只1条,存在有多条时即为“多线程”。1个CPU核执行多条不同路径上的不同命令。
OS X和iOS的核心XNU内核在发生操作系统事件时(如每隔一定时间,唤起系统调用等情况)会切换执行路径。例如CPU的寄存器等信息保存到各自路径专用的内存块中,从切换目标路径专用的内存块中,复原CPU寄存器等信息,继续执行切换路径的CPU命令列。这被称为“上下文切换”
由于使用多线程的程序可以在某个线程和其他线程之间反复多次进行上下文切换,因此看上去就好像1个CPU核能够并列地执行多个线程一样。而且在具有多个CPU核的情况下,就不是“看上去像”了,而是真的提供了多个CPU核并行执行多个线程的技术。
这种利用多线程编程的技术就被称为“多线程编程”
但是,多线程编程实际上是一种易发生各种问题的编程技术。比如多个线程更新相同资源会导致数据的不一致(数据竞争)、停止等待事件的线程会导致多个线程相互等待(死锁)、使用太多线程会消耗大量内存等。
主线程
一个程序运行后,默认会开启 1 个线程,称为“主线程”或“UI线程”
主线程一般用来
1. 刷新 UI 界面
2. 处理 UI 事件(比如:点击、滚动、拖拽等事件)
主线程使用注意
1. 别将耗时的操作放到主线程中
2. 耗时操作会卡住主线程,严重影响UI的流畅度,给用户一种卡的坏体验
耗时操作演练
- (void)demo {
NSInteger count =1000*10;NSTimeInterval start =CACurrentMediaTime();
/*
1. 循环的速度很快
2. 栈区操作很快
3. 常量操作很快
4. 堆区操作速度不快
5. 循环消耗 CPU 资源
6. I / O 操作速度慢
*/
for(NSInteger i =0; i < count; i++) {
NSInteger num = i;
NSString*text =@"hello";
NSString*name = [NSString stringWithFormat:@"%@ - %zd", text, num];
NSLog(@"%@", name);
}
NSLog(@"over %f",CACurrentMediaTime() - start);
}
多线程解决耗时操作示例代码
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent*)event {
// 直接调用//
[self demo];
//第一种方法
// [self performSelectorInBackground:@selector(demo) withObject:nil];
//第二种方法
[NSThreaddetachNewThreadSelector:@selector(demo) toTarget:selfwithObject:nil];
// 第三种方法
// dispatch_async(dispatch_get_global_queue(0, 0), ^{
// [self demo];
// });
}
多线程的原理
1. (单核CPU)同一时间,CPU 只能处理 1 个线程
换言之,同一时间只有 1 个线程在执行
2. 多线程同时执行:
是 CPU 快速的在多个线程之间的切换
CPU 调度线程的时间足够快,就造成了多线程的“同时”执行的效果
3. 如果线程数非常多
CPU 会在 N 个线程之间切换,消耗大量的 CPU 资源
每个线程被调度的次数会降低,线程的执行效率降低
多线程优/缺点
优点
1. 能适当提高程序的执行效率
2. 能适当提高资源的利用率(CPU,内存)
3. 线程上的任务执行完成后,线程会自动销毁
缺点
1. 开启线程需要占用一定的内存空间(默认情况下,每一个线程都占 512 KB)
2. 如果开启大量的线程,会占用大量的内存空间,降低程序的性能
3. 线程越多,CPU 在调用线程上的开销就越大
4. 程序设计更加复杂,比如线程间的通信、多线程的数据共享
多线程技术方案
网友评论