为了了解更多有关java编程语言的知识,今天为大家介绍一下java线程之间怎么转换,并且用图片详细解读它们之间的状态。
首先我们来看看线程状态之间的转换该怎么做?
最开始的是Runnable和Blocked状态之间的转换
看上图红色部分,如果线程进入synchronized修饰的代码块或者方法的话,但是没有获取到monitor的话就会进入Blocked状态;如果获取了monitor之后,就会再次进入Runnable状态。
然后是Runnable和Waiting以及Blocked之间的转换
从上图红色区域可以看出,进入waiting状态的线程,下一个状态可能为Blocked,也可能是Runnable。如果join线程执行结束或者被中断,或者调用LockSupport.unpark(this)可以进入Runnable状态。
如果其它线程调用了notify()或者notifyAll()来唤醒需要唤醒的线程,则会直接进入Blocked状态,为什么会出现这种情况?因为线程想要调用notify或者notifyAll()必须得持有monitor锁,当调用notify或者notifyAll()方法的时候,所在线程持有的monitor锁并不一定立马就释放,只有当释放了锁,并且被激活的线程得到了monitor锁才会从Blocked状态回到Runnable状态。
从上文我们可以得出的结论是,线程的生命周期是不可逆的,只有一次New和Terminated状态,线程的生命周期是按照本篇图中箭头的指向运行的,只有处于中间状态的才可以相互转换。
下面我们通过图片详细分析各种状态。
第一种是New状态
从图中我们可以看出来,New状态是线程生命周期的第一个状态。当调用new Thread()创建线程的时候,线程就处于New状态,如果调用了线程的start()方法,线程状态就会从New状态变为Runnable状态。
第二种是RUNNABLE状态
Runnable状态其实并不一定是在运行的状态,它内部包含了两种状态,真正的运行态Running和准备运行态Ready,当线程获取到了CPU的时间片之后就会处于Running状态,但是如果处于Running状态的线程的cpu被调度去做其它的任务了,线程就会处于Ready状态。
第三种是BLOCKED阻塞状态
如果要进入BLOCKED状态就只能是从Runnable状态进来的,New状态只能进入到Runnable状态。并且线程进入Blocked状态的条件只能是进入synchronized修饰的代码块或者方法,但是如果没有获取到monitor锁,就会处于Blocked阻塞状态。
第四种是 WAITING状态
进入Waiting状态的条件包括:object.wait(),thread.join(),LockSupport.park(this)。
在Blocked状态提到了,只有使用synchronized的方式才能进入Blocked状态,那假如用其他的加锁方式会是什么结果。比如我们熟知的reentrantLockawait()或者CountDownLatch.await()方式,查看源码很容易发现使用的都是LockSupport.park()的方式。都会进入Waiting状态。
这里Blocked和Waiting状态就会产生一些对比,Blocked状态是线程在等待其它线程释放锁,而Waiting则是在等待某一个条件,比如object.wait()的条件是object.notify()或者object.notifyAll(),如果没有这些条件唤醒线程的话,可能线程一直处于阻塞状态所以使用的时候要格外小心。如果是thread.join()的话,就需要插入的线程执行结束才可能触发线程。
第五种是 TIMED WAITING状态
TIMED WAITING状态和WAITING状态的区别就是多了一个时间的限制而已,当时间超时的话,就会自动由系统唤醒线程,或者被唤醒信号唤醒。
想要进入TIMED WAITING状态方式包括:object.wait(time),Thread.sleep(time),thread.join(),LockSupport.parkNanos(time),LockSupport.parkUntil(time)。
第六种是TERMINATED状态
进入TERMINATED状态,有两种方式,要么是程序正常运行结束,run方法执行完毕。
要么是异常结束,中断了run方法了执行,导致程序结束。
总而言之,java编程语言的学习任重而道远,想要了解更多有关java的常见问题,敬请关注奇Q工具网。
推荐阅读: