- 线程的生命周期
一个完整的线程生命周期,要经过 新建
(new)、就绪
(Runnable)、运行
(Running)、阻塞
(Blocked)和死亡
(Dead)5种状态。
new阶段
new阶段就是你new Thread()创建线程对象时候的阶段。
new阶段下其实线程根本还是不存在
的,我们只是创建了一个Therad对象
,就和我们最常用的new关键字是一个道理。
只有当我们真正把线程启动起来的时候,此时才会在JVM进程
中把我们的线程创建出来。
我们new了一个Thread对象之后就需要调用Thread.start()来启动线程,此时线程会从new
阶段转换到Runnable
阶段。
Runnable阶段
只有调用Thread.start()方法才能使线程从new阶段转换到Runnable阶段。
当然我们从字面意思也可以知道此时线程是处于可执行转状态
而不是真正的执行中
状态了,此时的线程只能等CPU翻牌子,翻到了他才能真正的跑起来。
有些同学可能会说要是CPU一直不翻牌子咋办?严格意义上来讲,处在Runnable的线程只有两条出路,一条是线程意外退出
,还有一条是被CPU翻牌子进入Running
阶段。
3.Running阶段
有了解过这块内容的同学看到这里可能会有疑问,java线程状态中并没有这个状态
,为什么我们在讲生命周期的时候会把这一状态单独拆分出来做讲解?为了章节内容的流畅性,这块内容的解释放到下一节去讲解,这边我们还是继续讲我们的线程生命周期。
好的我们继续
这个阶段的线程已经获取到了CPU调度执行权,也就是说处于运行中状态了。
在该阶段中,线程可以向前或者向后发生转换:
-
由于CPU的调度器轮询导致该线程放弃执行,就会进入
Runnable
阶段。 -
线程主动调用yield,放弃CPU执行权,就会进入
Runnable
阶段(这种方式并不是百分百生效的,在CPU资源不紧张的时候不会生效)。 -
调用sleep、wait方法,进入
Blocked
阶段(这里讲的Blocked阶段和线程的Blocked状态需要区分开,这边讲的是一个比较广义的Blocked的阶段) -
进行某个阻塞的IO操作而进入
Blocked
阶段 -
为了获取某个锁资源而加入到该锁到阻塞队列中而进入
Blocked
阶段 -
线程执行完成或者调用stop方法或者判断某个逻辑标识,直接进入
Terminated
阶段
Blocked阶段
进入该阶段的原因已经在Running阶段阐述过了,这里就不再说明,这里主要介绍一下处于该阶段的线程可以如何切换。
-
直接进入
Terminated
,比如调用stop
方法或者意外死亡(JVM Crash
) -
线程
阻塞
的操作结束,读取或者写入了想操作的数据进入Runnable
状态 -
线程完成了指定时间的
休眠
,进入Runnable
状态 -
Wait状态的线程被
notify
或者notifyall
唤醒,进入Runnable
状态 -
获取到了
锁资源
,进入Runnable
状态 -
线程阻塞过程
被打断
,比如调用interrupt
方法,进入Runnable
状态
Terminated状态
Terminated
状态是一个线程的最终状态,在该状态中线程不会切换到其他任何状态。
线程进入Terminated
状态意味着线程整个生命周期结束了,进入Terminated状态的方式有以下三种
:
-
线程正常结束
-
线程意外结束
-
JVM Crash