前言: 本教程分为多个章节, 由每个章节循序渐进地从零讲解java多线程相关的技术知识,部分内容参考自《Java多线程编程核心技术》。 |
进程和线程的概念
进程的理解
先看一下对进程百度的结果:
乍一看这段话会觉得比较抽象难理解,可以先看一下下图:
通过此图可以看出图中用红色框出的部分都是进程, 如活动监视器、QQ、Chrome浏览器等。
我们常用的QQ、微信、迅雷、浏览器等都是进程; 一个软件或一个应用就是一个进程。
线程的理解
同样先看一下对线程百度的结果:
这一大串文字看着同样比较抽象难以理解,老套路,我们再看一下下图:
通过此图可以看出图中用红色框出的部分都是线程, 由此我们可以发现一个进程下会有1个或多个线程,线程是一个程序执行期间的最小单元; 比如QQ下的文字传输、语音传输、对话框窗口抖动等都是线程。
进程和线程的关系通俗来讲就是: 进程就是爹妈, 线程就是子女, 爹妈(进程)管理着一个或多个子女(线程)。
进程的简单延伸
进程的切换
进程的切换就是指把正在运行的进程收回到处理器, 然后再让等待运行的进程来占用处理器。
收回到处理器) : 实际上就是把进程存放在处理器中的寄存器里面的数据找个地方存起来(存到进程的私有堆栈中), 然后把腾出空间 的处理器中的寄存器交给其他进程来使用。
占用处理器) : 实际上就是把进程存在私有堆栈里的数据再恢复到处理器中的寄存器里,然后把等待运行的进程的断点送到寄存器 中的程序指针PC,这个进程就开始被处理器运行了,也就是这个进程占用了处理器。
这两个切换行为通俗理解就是比如我们平时工作中用到的工位这个场景,现在情况来了,由于领导的安排需要我们和另外一个同事换个工位,具体什么原因这里也不讨论,拥有绝对执行力的我们要坚决服从领导的安排,所谓的收回就是我们得把工位上的东西拿走,所谓的占用就是同事把他的东西放在工位上。
PS: 在进程切换的时候,一个进程在处理器中寄存器里面的数据称为进程的上下文,所以呢进程的切换也就是被终止的进程与等待的进程的上下文的切换。
进程的三个基本状态
1) 就绪状态(Ready)
2) 运行状态(Running)
3) 阻塞状态(Blocked)
进程的调度算法
实时系统中) : FIFO算法(先入先出), SJF算法(最短作业优先), SRTF算法(最短剩余时间优先)等。
交互式系统中) : RR算法(时间片轮转), HPF算法(最高优先级), 多级队列, 最短进程优先, 公平分享调度等。
线程的简单延伸
线程的切换
不管是单核的CPU还是多核的CPU都支持多线程执行代码,线程的切换只需更改一些寄存器的指针,如PC、PD等寄存器,当然这些是通过硬件来实现的,效率很快,当前线程的任务执行一个时间片后会切换到下一个线程任务,在切换前后保存这个任务的状态以便下次切换回这个任务时可以再次加载到这个任务的状态; 从任务的状态保存到再加载的过程称为线程的上下文切换。
线程的切换过程:
1. 虚拟机启动之后,进入解释器的循环,这个循环会一直解释执行pc指针对应的java字节码。
2. 每个线程都有一个线程栈,在调用的时候会在栈上分配栈帧由sp、fp等指针指向。
3. 线程调度就是记录下当前线程的sp、fp等指针(这些指针都是全局的),并将这几个指针指向下一个将要执行的线程的相应位置。
4. 当恢复上面几个指针之后,就切换回之前的线程了。
举个例子理解一下线程的切换: 作为爱学习的我们都少不了看一些技术框架的官方api,这些api大多都是英文的,在看api时遇到了某个不认识的单词,我们要去翻译这个单词的意思,但在翻译之前我们必须要记住api我们看到了哪里,等知道了单词的意思之后以便我们继续看api,如果我们英文比较水,单词词汇量比较少的话就免不了我们要多次的去查单词的意思,这样一来肯定会影响我们看api的效率,同样上下文的切换也会影响多线程的执行效率。
线程的五个基本状态
1) 新建状态(New)
2) 就绪状态(Runnable)
3) 运行状态(Running)
4) 阻塞状态(Blocked)
5) 死亡状态(Dead)
线程的调度算法
FIFO算法(先入先出)、HPF算法(优先级)、RR算法(时间片轮转调度)。
进程和线程的简单延伸之协程
用自己的话来说协程就是用户级的轻量级线程。
应用程序可以粗略的分为cpu密集型应用和io密集型应用。
在并发编程中协程和线程比较类似,都有自己的本地数据,一个协程表示一个执行单元,它与其它协程共享全局数据和其它的资源。
协程的优点:
1)跨平台
2)跨体系架构
3)无须线程上下文切换的开销
4)无须原子操作锁定和同步的开销
5)更适合高并发,高并发+低成本+高拓展性
协程的缺点:
1)无法利用多核资源,协程本身是单线程的,它不能同时把单个cpu的核全部应用上
2)进行阻塞操作时会阻塞住整个应用程序
JAVA中的协程框架
1)Akka
2)Kilim
章尾
本章主要介绍了多线程相关的概念知识(进程、线程、协程),本章作为Java多线程开发的“开胃小菜”,大多介绍了偏概念性、偏抽象的知识,部分朋友看着可能会引起一点不适且感到枯燥,请收起各位的大刀,原谅小弟!
希望这道“开胃小菜”没有影响各位品尝后面的硬菜 — Java多线程技术的食欲和胃口~~~
在后续的章节中将正式进入Java多线程相关的干货知识,敬请期待...