乐趣区

关于java:Java线程状态详解

Java 的每个线程都具备本人的状态,Thread 类中成员变量 threadStatus 存储了线程的状态:

private volatile int threadStatus = 0;

在 Thread 类中也定义了状态的枚举,共六种,如下:

public enum State {
    NEW,            //    新建状态
    RUNNABLE,        //    执行状态
    BLOCKED,        //    阻塞状态
    WAITING,        //    无限期期待状态
    TIMED_WAITING,  //  有限期期待状态
    TERMINATED;     //  退出状态
}

threadStatus 初始值为 0,对应的就是 NEW 状态。

  • NEW:新建状态,new Thread() 时处于这个状态,此时线程还未开始执行
  • RUNNABLE:执行状态,当调用了 start 办法后,线程处于此状态,当然此刻 CPU 不肯定正在执行它
  • BLOCKED:阻塞状态,线程期待锁时处于此状态
  • WAITING:无限期期待状态,须要被唤醒的期待属于此状态,如 Object.wait
  • TIMED_WAITING:有限期期待状态,调用一些有超时工夫的期待办法会进入此状态,如 Thread.sleep、Object.wait、Thread.join、Lock.tryLock、Condition.await
  • TERMINATED:退出状态,可能是失常运行结束,也可能是抛出了异样导致线程终止

咱们能够通过 getState 获取线程的状态:

State state = thread.getState();

接下来,咱们通过示例来感触线程状态的变动。

示例一:

Thread t = new Thread(() -> {System.out.println("sleep");
    //    休眠 2 秒
    ThreadUtil.sleep(2000);
    System.out.println("run");
});

//    启动前先打印一下线程状态
System.out.println(t.getState());
//    启动线程
t.start();
//    启动后立刻打印一次线程状态
System.out.println(t.getState());

//    每隔 500 毫秒打印一次线程状态
while (true) {ThreadUtil.sleep(500);
    System.out.println(t.getState());
}

输入:

NEW
RUNNABLE
sleep
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
run
TERMINATED
TERMINATED
TERMINATED
TERMINATED
TERMINATED
TERMINATED
TERMINATED

能够看出,线程创立后,初始状态为 NEW;
调用 start 办法后状态变更为了 RUNNABLE;
当线程内执行了 sleep,休眠 2 秒钟,状态变更为了 TIMED_WAITING;
当线程执行实现后,状态变更为了 TERMINATED。

示例二:
本示例演示在多线程争抢锁的状况下,线程状态的变动。

private static Object lock = new Object();

public static void main(String[] args) {Runnable runnable = () -> {
        //    加锁
        synchronized (lock) {System.out.println(Thread.currentThread().getName() + "lock");
            ThreadUtil.sleep(2000);
        }
        System.out.println(Thread.currentThread().getName() + "exit");
    };

    Thread t1 = new Thread(runnable, "t1");
    Thread t2 = new Thread(runnable, "t2");

    t1.start();
    t2.start();

    while (true) {ThreadUtil.sleep(500);
        System.out.println(t1.getName() + ":" + t1.getState());
        System.out.println(t2.getName() + ":" + t2.getState());
    }
}

输入:

t1 lock                t1 取得了锁
t1:TIMED_WAITING    t1 sleep,进入无限期待状态
t2:BLOCKED          t2 未取得锁,因而进入阻塞状态
t1:TIMED_WAITING    
t2:BLOCKED
t1:TIMED_WAITING
t2:BLOCKED
t1 exit             t1 开释锁,执行实现,退出
t2 lock             t2 取得锁
t1:TERMINATED       t1 曾经是退出状态
t2:TIMED_WAITING    t2 sleep,进入无限期待状态
t1:TERMINATED       
t2:TIMED_WAITING
t1:TERMINATED
t2:TIMED_WAITING
t1:TERMINATED
t2:TIMED_WAITING
t2 exit            t2 开释锁,执行实现,退出
t1:TERMINATED      t1 为退出状态
t2:TERMINATED      t2 为退出状态 

示例三:
本示例演示了线程如何进入和退出 WAITING 状态。

private static Object obj = new Object();

public static void main(String[] args) {Runnable runnable = () -> {synchronized (obj) {
            try {
                //    期待
                obj.wait();} catch (InterruptedException e) {e.printStackTrace();
            }
            System.out.println("exit");
        }
    };

    Thread t1 = new Thread(runnable, "t1");
    System.out.println(t1.getName() + ":" + t1.getState());
    t1.start();
    System.out.println(t1.getName() + ":" + t1.getState());

    for (int i = 0; i < 20; i++) {ThreadUtil.sleep(500);
        if(i == 3) {synchronized (obj) {
                //    唤醒
                obj.notify();}
        }
        System.out.println(t1.getName() + ":" + t1.getState());
    }
}

输入:

t1:NEW
t1:RUNNABLE
t1:WAITING    调用了 obj.wait() 进入有限期待状态
t1:WAITING
t1:WAITING
t1:BLOCKED  主线程取得锁,进行 notify,t1 进入了阻塞状态
exit               t1 线程退出同步块,执行实现
t1:TERMINATED  t1 线程退出
t1:TERMINATED

Java Thread 的 threadStatus 字段值的更新代码位于 hotspot c++ 源码中,JDK 源码中看不到。
Java 的线程状态并非是操作系统的理论线程状态,但与操作系统的线程状态是有对应关系的,后续有须要深入分析操作系统原理、hotspot 源码再开展。

退出移动版