原来还能这么看Java线程的状态及转换

大家好 , 我是呼噜噜 , 最近一直在梳理JAVA并发 , 但内容杂且偏晦涩 , 今天我们一起来聊聊Java 线程的状态及转换 先来夯实一下基础 , 万丈高楼平地起 , 路还是得慢慢走 。
Java线程的生命周期我们先来看下Java线程的生命周期图:

原来还能这么看Java线程的状态及转换

文章插图
 
上图也是本文的大纲 , 我们下面依次聊聊java各个线程状态及其他们的转换 。
线程初始状态线程初始状态(NEW): 当前线程处于线程被创建出来但没有被调用start()
在Java线程的时间中 , 关于线程的一切的起点是从Thread 类的对象的创建开始 , 一般实现Runnable接口 或者 继承Thread类的类 , 实例化一个对象出来 , 线程就进入了初始状态
Thread thread = new Thread()由于线程在我们操作系统中也是非常宝贵的资源 , 在实际开发中 , 我们常常用线程池来重复利用现有的线程来执行任务 , 避免多次创建和销毁线程 , 从而降低创建和销毁线程过程中的代价 。Java 给我们提供了 Executor 接口来使用线程池 , 查看其JDK1.8源码 , 发现其内部封装了Thread t = new Thread()
public class Executors {...static class DefaultThreadFactory implements ThreadFactory {private static final AtomicInteger poolNumber = new AtomicInteger(1);private final ThreadGroup group;private final AtomicInteger threadNumber = new AtomicInteger(1);private final String namePrefix;...public Thread newThread(Runnable r) {Thread t = new Thread(group, r,namePrefix + threadNumber.getAndIncrement(),0);if (t.isDaemon())t.setDaemon(false);if (t.getPriority() != Thread.NORM_PRIORITY)t.setPriority(Thread.NORM_PRIORITY);return t;}}...}在thread类源码中 , 我们还能发现线程状态的枚举类State:
public enum State {/*** Thread state for a thread which has not yet started.*/NEW,RUNNABLE,BLOCKED,WAITING,TIMED_WAITING,/*** Thread state for a terminated thread.* The thread has completed execution.*/TERMINATED;}所谓线程的状态 , 在java源码中都是通过threadStatus的值来表示的
/* Java thread status for tools,* initialized to indicate thread 'not yet started'*/private volatile int threadStatus = 0;State 和 threadStatus 通过toThreadState方法映射转换
public State getState() {// get current thread statereturn sun.misc.VM.toThreadState(threadStatus);}//--- --- ---public static State toThreadState(int var0) {if ((var0 & 4) != 0) {return State.RUNNABLE;} else if ((var0 & 1024) != 0) {return State.BLOCKED;} else if ((var0 & 16) != 0) {return State.WAITING;} else if ((var0 & 32) != 0) {return State.TIMED_WAITING;} else if ((var0 & 2) != 0) {return State.TERMINATED;} else {return (var0 & 1) == 0 ? State.NEW : State.RUNNABLE;}}到这里我们就可以发现 , Thread t = new Thread()在Java中只是设置了线程的状态 , 操作系统中并没有的实际线程的创建
线程运行状态线程运行状态(RUNNABLE) , 线程被调用了start()等待运行的状态
在linux操作系统层面 , 包含Running和 Ready状态 。其中Ready状态是等待 CPU 时间片 。现今主流的JVM , 比如hotspot虚拟机都是把Java 线程 , 映射到操作系统OS底层的线程上 , 把调度委托给了操作系统 。而操作系统比如Linux,它是多任务操作系统 , 充分利用CPU的高性能 , 将CPU的时间分片 , 让单个CPU实现"同时执行"多任务的效果 。
Linux的任务调度又采用抢占式轮转调度 , 我们不考虑特权进程的话 , OS会选择在CPU上占用的时间最少进程,优先在cpu上分配资源 , 其对应的线程去执行任务 , 尽可能地维护任务调度公平 。Running和 Ready状态的线程在CPU中切换状态非常短暂 。大概只有 0.01 秒这一量级 , 区分开来意义不大 , java将这2个状态统一用RUNNABLE来表示
thread.start()源码解析我们接下来看看为什么说执行thread.start()后 , 线程的才"真正的创建"
public class ThreadTest {/*** 继承Thread类*/public static class MyThread extends Thread {@Overridepublic void run() {System.out.println("This is child thread");}}public static void main(String[] args) {MyThread thread = new MyThread();thread.start();}}其中thread.start()方法的源码中 , 会去调用start0()方法 , 而start0()是private native void start0();JVM调用Native方法的话 , 会进入到不受JVM控制的世界里


推荐阅读