天天看点

死磕并发之线程的生命周期详解

文章开始大家思考一个问题,执行了Thread的start方法之后就代表该线程已经开始执行了吗?相信大家看完文章应该就能找到答案。

一.线程的生命周期大致分为以下5个阶段

1.NEW

2.RUNNABEL

3.RUNNING

4.BLOCKED

5.TERMINATED

接下来让我们看下这5个阶段分别代表什么。

二.线程的NEW状态

我们使用new关键字创建一个Thread对象时,它只是Thread对象的一个状态。指的是线程已经被创建,但是还不允许分配CPU执行,这个状态是编程语言特有的,这里的创建也只是编程语言层面的被创建,在操作系统层面,线程还没有被真正创建。

三.线程的RUNNABEL状态

线程对象进入RUNNABEL状态必须调用start方法,此时操作系统层面的线程才被真正创建,线程可以分配CPU执行。

线程一经创建就能立即得到执行吗?答案是否定的,线程的运行与否要听令CPU的调度,也就是说它具备执行的资格,但是并没有真正地执行起来,而是要等待CPU的调度。

回到我们文章开头的问题,相信大家已经有了答案。

四.线程的RUNNING状态

一旦CPU通过轮询或者其他方式从任务可执行队列选中了线程,那么此时它才能真正地执行自己的逻辑代码。需要注意一个处于RUNNING状态的线程事实上也是RUNNABLE的,但反之不成立。

在该状态中,线程状态会发生如下状态转换。

1.直接进入TERMINATED状态,比如直接调用已经过时的stop方法或者判断某个逻辑标识。

2.进入BLOCKED状态,比如调用了sleep,或者wait方法而加入了waitSet中。

3.进行某个阻塞的IO操作,比如因网络数据的读写而进入BLOCKED状态。

4.获取某个锁资源,从而加入到该锁的阻塞队列中而进入BLOCKED状态。

5.由于CPU调度器轮询使该线程放弃执行,进入RUNNABLE状态。

6.线程主动调用yield方法,放弃CPU执行权,进入RUNNABEL状态。

五.线程的BLOCKED状态。

调用sleep或者wait方法会使线程进入BLOCKED状态(需要注意的是,sleep方法不会释放锁资源,wait会释放锁的资源)。

线程在BLOCKED状态下可切换如下几种状态。

1.直接进入TERMINATED状态,比如直接调用过时stop方法或者意外死亡(JVM Crash)。

2.线程阻塞操作结束,比如读取了想要的数据字节接入到RUNNABLE状态。

3.线程完成率指定时间的休眠,进入到了RUNNABLE状态。

4.wait中的线程被其他线程notify/notifyAll唤醒,进入RUNNABLE状态。

5.线程获取到了某个锁的资源,进入RUNNABLE状态。

6.线程在阻塞过程中被打断,比如其他线程调用了interrupt方法,进入RUNNABLE状态。

六.线程的TERMINATED状态。

TERMINATED是一个线程的最终状态,在该状态中线程不会切换到其他任何状态,线程进入TERMINATED意味着该线程的整个生命周期都结束了。

下列这些情况会使线程进入TERMINATED状态。

1.线程正常运行结束。

2.线程运行出错意外结束。

3.JVM Crash导致所有的线程都结束。