Java线程状态转换图(包含wait和sleep)
在网上看到了很多关于线程状态转换图,我认为下面这个是描述的最为精确的一个,当然这个图是在参考别人的基础上修改得到的。下面我会对这个图做详细的说明,因为原图中的描述很少,不够详细。
在接下来的博文中,我会就java问题的线程的使用做详细的介绍。
为什么说上面这个图是比较详细的,是因为上图中描述了wait方法和sleep方法在线程中的作用,具有很强的实践意义。
由上图可知线程分为5个状态,创建(new)、可执行(runnable)、执行(running)、阻塞(block、sleep和wait)和结束(dead)。
1. 创建阶段:创建一个新的线程,系统为线程分配线程执行所需要的非CPU资源的时候(在JVM中,为线程分配私有的虚拟机栈,本地方法栈和程序计数器),线程的状态转换成可执行状态。
2. 可执行阶段:在此阶段的线程获得了CPU的时间片的时候即刻进入执行阶段。
3. 执行阶段:在执行阶段程序可能遇到三种情况,第一种是程序自动放弃时间片就进入阻塞阶段;第二种是程序执行完时间片就会进入到可执行状态,等到再次获得时间片之后继续执行程序;第三种是程序执行完成或者在执行时异常产生,程序结束执行。
4. 阻塞阶段:在此阶段,程序主动放弃在CPU执行的时间片,在此阶段调用方法sleep、wait方法、遇到锁或者遇到长时间不使用CPU的操作(长时间是相对而言的)。经过阻塞之后程序就进入了可执行阶段。其中理解wait方法和sleep方法对于资源的占有情况对于线程的理解很有好处。
5. 结束阶段:在此阶段JVM销毁线程对象并且释放JVM分配的资源,即自动GC。
最后我们看看wait和sleep的区别(很重要):
1)wait:首先看一下java(J2SE8)的官方文档上是怎么说的
由上图可知在执行wait方法时,当前线程会释放监视器的所有权,即是释当前所拥有的资源,让给其他线程使用。而且在调用wait方法之后需要使用notify或者notifyAll方法、中断或者在等待时间大于时间参数才能唤醒。更坑爹的是wait必须在同步快内才能使用,sleep方法的没有这个限制。
2)sleep:同理
上图可知sleep方法不会失去任何监视器的所有权,即是sleep的睡眠其实是线程在执行计数,也就是说线程是不会释放任何所拥有的资源。