为什么Java里面线程没有Running状态?


0d569f1ff6631949f60e2b659fea0410.jpeg

0d2b7982339268bad50479b88578f9c9.jpeg

c22421d481df54c3bc3020c8e98dded0.jpeg

d510eead1f685b7ede32a13b9cd0d92e.jpeg

b15e71b45171506d27d88e06a2291e1d.jpeg

f2a06364d9f049779a9563fc9a847785.jpeg

8f15b32461d8942949816cb9af785b72.jpeg

在多线程操作系统中,通常是在一个进程中包括多个线程,每个线程都是作为利用CPU的基本单位,是花费最小开销的实体。

线程是有状态的,线程的状态被定义在Thread.State枚举中,在Java Doc中也有明确的解释:

6332a6352b2c33098bdfbc68bf9a1614.jpeg

通过查看源码以及阅读Java Doc,我们可以知道,线程主要有以下6种状态:

  • NEW

    • 当一个线程被创建出来的,但是还没调用start()方法的时候,他处于NEW状态。

  • RUNNABLE

    • 在Java虚拟机中执行的线程处于这种状态

  • BLOCKED

    • 正在等待锁的阻塞线程处于这种状态。

  • WAITING

    • 不确定地等待另一个线程执行某个特定操作的线程就是处于这种状态,进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)。

  • TIMED_WAITING

    • 在指定的等待时间内等待另一个线程执行某个操作的线程处于这种状态。该状态不同于WAITING,它可以在指定的时间后自行返回。

  • TERMINATED

    • 已经退出的线程处于这种状态。

在指定的时间点,线程只能处于一种状态。但是需要注意的是这些状态表示的是虚拟机中线程的状态,而不是任何操作系统线程状态。

34bf6f64c58780502462c8e9ff5b3190.jpeg

772dbb4472e138c57468b86cadf9e5ec.jpeg

线程之间的状态是可以互相转换的,如下图:

8ddaf8812bfa2e6c49cd4b8536566520.jpeg

上图,就是线程的6种状态的转换图,当遇到不同的操作或者事件的时候,线程的状态就可能发生变化。

Java Doc中说在Java虚拟机中正在执行的线程处于RUNNABLE状态,但是,在操作系统层面,一个线程要想被执行,是需要获得CPU的使用权的。

d8d207bb0bc0cf280da697982cdee83b.jpeg

dde02f2bc5133827ae76ee300c2981f5.jpeg

064cd0253aa5a2829b9b455ee94b80f1.jpeg

4f4f9352e07ffdadff3569da51811878.jpeg

我们其实还可以把RUNNABLE状态进一步细化一下,根据线程是否获得了CPU的使用权分成两种:

  • 就绪(READY):线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中并分配cpu使用权 。

  • 运行中(RUNNING):就绪(READY)的线程获得了cpu 时间片,开始执行程序代码。

54550dbde6ba3ee0d558a125946158f7.jpeg

也就是说,当一个线程被创建出来之后,执行了start方法之后,在没有获得cpu的使用权的时候,他就是就绪状态(READY),在获得了CPU的使用权,开始执行的时候,就是运行状态(RUNNING)了。

dd2d9e31255f723b261d7f237b8d1910.jpeg

7e0bc630237c25e2c5fafb0f5fea2a8b.jpeg

81b83f1941d4e35c90d01eb1e5de2385.jpeg

eb1970e92549020cd907d0cc623324e6.jpeg

为什么没有定义RUNNING状态?

对于现在的分时操作系统来说,在单CPU情况下,所有的线程其实都是串行执行的。但是为了让我们看起来像是在并发执行,人们把CPU的执行分成很多个小的时间片。

哪个进程得到时间片,那个线程就执行,时间片到了之后,就要释放出CPU,再重新进行争抢时间片。

只要把时间片划分的足够细,那么多个程序虽然在不断的串行执行,但是看起来也像是在同时执行一样。

1ac37f1271dd2dd667578f61a7568427.jpeg

那么,CPU的时间片其实是很短的,一般也就是10-20毫秒左右。

那么,也就是说,在一秒钟之内,同一个线程可能一部分时间处于READY状态、一部分时间处于RUNNING状态。

那么如果,明确的给线程定义出RUNNING状态的话,有一个很大的问题,就是这个状态其实是不准的。

因为当我们看到线程是RUNNING状态的时候,很有可能他已经丢失了CPU时间片了。

对于线程的状态,我们只需要知道,他当前有没有在"正在参与执行"就行了,何为"参与执行"?

就是他的状态是可执行的,只要获得时间片,就能立即执行。

那这不就是RUNNABLE吗?

所以,Java就没有给线程定义RUNNING状态,而是定义了一个RUNNABLE状态。

5c75401113034704ecbc378a30462e43.jpeg

55570e97750e25f8978809d4e69bcc32.jpeg

962b7696dacd793c96f2cd3da9ee8b95.jpeg

28592e5fccb758b6156b324a8d854113.jpeg

64f6de33dda399f16a929d728a6cf4b2.jpeg

37301d406af1fd7ef5b578525f71590b.jpeg

猜你喜欢

转载自blog.csdn.net/jjc4261/article/details/125781216