一、java线程状态

1.1 线程状态

OS的进程状态

image.png
注:这里的进程指早期的单线程进程,这里所谓进程状态实质就是线程状态。

JVM的线程状态

image.png
这里说的 Java 线程状态均来自于 Thread 类下的 State 这一内部枚举类中所定义的状态,与操作系统底层的线程状态是两个不同层面的事。

关联

image.png
RUNNABLE 状态对应了传统的 ready, running 以及部分的 waiting 状态。

1.2 RUNNABLE

定义

一个在 JVM 中执行的线程处于这一状态中。(A thread executing in the Java virtual machine is in this state.)

与OS中ready的联系
  1. 处于runnable 状态下的线程正在 Java 虚拟机中执行,但它可能正在等待来自于操作系统的其它资源,比如处理器。
  2. 所以runnable 状态实质上是包括了OS的 ready 状态的,甚至还可能有包括OS中的 waiting 状态的部分细分状态。
与OS中running的联系
  1. 对 Java 线程状态而言,不存在所谓的running 状态,它的 runnable 状态包含了 running 状态。
  2. 现在的时分(time-sharing)多任务(multi-task)操作系统架构通常都是用所谓的“时间分片(time quantum or time slice)”方式进行抢占式(preemptive)轮转调度(round-robin式)。
  3. 这个时间分片通常是很小的,一个线程一次最多只能在 cpu 上运行比如10-20ms 的时间(此时处于 running 状态),也即大概只有0.01秒这一量级,时间片用后就要被切换下来放入调度队列的末尾等待再次调度。(也即回到 ready 状态)
  4. 通常,Java的线程状态是服务于监控的,如果线程切换得是如此之快,那么区分 ready 与 running 就没什么太大意义了,当看到监控上显示是 running 时,对应的线程可能早就被切换下去了。
  5. 现今主流的 JVM 实现都把 Java 线程一一映射到操作系统底层的线程上,把调度委托给了操作系统,我们在虚拟机层面看到的状态实质是对底层状态的映射及包装,JVM 本身没有做什么实质的调度
  6. 处于 runnable 状态下的线程正在* Java 虚拟机中执行,但它可能正在等待来自于操作系统的其它资源,比如处理器、硬盘、网卡等,只要有东西在为线程服务,它就认为线程在“执行”。

1.3 IO阻塞

  1. 传统的I/O都是阻塞式(blocked)的,原因是I/O操作比起cpu来实在是太慢了,差到几个数量级。
  2. 解决办法:一旦线程中执行到 I/O 有关的代码,相应线程立马被切走,然后调度 ready 队列中另一个线程来运行。
  3. 这时执行了 I/O 的线程就不再运行,即被阻塞。不会被放到调度队列中去,因为很可能再次调度到它时,I/O 可能仍没有完成。线程会被放到所谓的等待队列中,处于上图中的 waiting 状态。
  4. 所谓阻塞只是指这段时间 cpu 暂时不会理它了,但另一个部件比如硬盘则在努力地为线程服务。
  5. 而当 I/O 完成时,则用一种叫中断(interrupt)的机制来通知 cpu:也即所谓的“中断驱动(interrupt-driven)”,现代操作系统基本都采用这一机制。
  6. 进行阻塞式 I/O 操作时,Java 的线程状是RUNNABLE。

Q.E.D.

知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议