文章目录
一、基本概念
程序:是为完成特定任务、用某种语言编写的一组指令的集合。即一段静态的代码 ,静态对象。
进程:是程序的一次执行过程,或是正在运行的一个程序 。是一个动态的过程:有它自身的产生、存在和消亡的过程。——生命周期
- 如:运行中的QQ,运行中的MP3播放器
- 程序是静态的,进程是动态的
- 进程是系统进行资源分配和调度的基本单位 ,系统在运行时会为每个进程分配不同的内存区域
线程:进程可进一步细化为线程,是一个程序内部的一条执行路径。
- 若一个进程同一时间并行执行多个线程,就是支持多线程的
- 线程作为CPU(或任务调度和执行)的基本单位,每个线程拥有独立的运行栈和程序计数器(pc) ,线程切换的开销小
- 一个进程中的多个线程共享相同的内存单元/内存地址空间—>它们从同一堆中分配对象,可以访问相同的变量和对象。这就使得线程间通信更简便、高效。但多个线程操作共享的系统资源可能就会带来安全隐患
二、进程与线程的区别:
- 每个进程拥有自己的一整套变量,是操作系统中资源分配的最小单位。线程依托于进程存在,多个线程共享进程的资源,线程是操作系统中任务调度的基本单位。
- 启动/撤销一个进程的开销要比启动/撤销一个线程大的多(线程轻量级)。
- 没有进程就没有线程,进程一旦终止,其内的线程全部撤销。
三、为什么说线程是CPU(或任务调度)的基本单位
操作系统在分配资源时是把资源分配给进程的,但是CPU资源比较特殊,它是被分配到线程的,因为真正要占用CPU运行的是线程,所以也说线程是CPU分配的基本单位。
四、进程与线程的关系
- 每个线程各自有一套虚拟机栈和程序计数器
- 每个进程有一份方法区和堆,而一个进程中拥有多个线程,则意味着多个线程共享方法区和堆
4.1 程序计数器
是一块内存区域,用来记录线程当前要执行的指令地址。
4.2 为何要将程序计数器设为私有呢?
我们知道线程是CPU执行的基本单位,而CPU一般是使用时间片轮转方式让线程轮询占用的,所以当前线程CPU时间片用完后,要让出CPU,等下次轮到自己的时候再执行。那么如何知道之前程序执行到哪里了呢?其实程序计数器就是为了记录该线程让出CPU时的执行地址的,待再次分配到时间片时线程就可以从自己私有的计数器指定地址继续执行。另外需要注意的是,如果执行的是native方法,那么pc计数器记录的是undefind地址,只有执行的是Java代码时pc计数器记录的才是下一条指令的地址。
4.3 虚拟机栈
每个线程都有自己的栈资源,用于存储该线程的局部变量,这些局部变量是该线程私有的,其他线程是访问不了的,除此之外栈还用来存放线程的调用栈帧。
4.4 堆
是一个进程中最大的一块内存,堆是被进程中的所有线程共享的,是进程创建时分配的,堆里面主要存放使用new操作创建的对象实例。
4.5 方法区
用来存放JVM加载的类、常量及静态变量等信息,也是线程共享的。
五、为什么使用多线程?
- 减少程序的响应时间
- 与进程相比,线程的创建和切换开销更小
- 在多CPU计算机上使用多线程能提高CPU的利用率
- 使用多线程能简化程序的结构,使程序便于理解和维护
六、线程状态
- 创建:当一个Thread类或其子类的对象被声明并创建时,新生的线程对象处于创建状态
- 就绪:处于创建状态的线程被start后,将进入线程队列等待cpu时间片,此时它已具备了运行的条件,只是没分配到cpu资源
- 运行:当就绪的线程被调度并获得cpu资源时,便进入运行状态,run方法定义了线程的操作和功能
- 阻塞:在某种特殊情况下,被人为挂起或执行输入输出仓做时,让出cpu并临时终止自己的执行,进入阻塞状态
- 终止:线程完成了它的全部工作,或线程被提前强制性的终止或出现异常导致结束