【概述】
1). java.lang.Thread 类中定义了一个枚举 State, 定义了线程的六种状态:NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED
public enum State { /** * Thread state for a thread which has not yet started. */ NEW, /** * Thread state for a runnable thread. A thread in the runnable * state is executing in the Java virtual machine but it may * be waiting for other resources from the operating system * such as processor. */ RUNNABLE, /** * Thread state for a thread blocked waiting for a monitor lock. * A thread in the blocked state is waiting for a monitor lock * to enter a synchronized block/method or * reenter a synchronized block/method after calling * {@link Object#wait() Object.wait}. */ BLOCKED, /** * Thread state for a waiting thread. * A thread is in the waiting state due to calling one of the * following methods: * <ul> * <li>{@link Object#wait() Object.wait} with no timeout</li> * <li>{@link #join() Thread.join} with no timeout</li> * <li>{@link LockSupport#park() LockSupport.park}</li> * </ul> * * <p>A thread in the waiting state is waiting for another thread to * perform a particular action. * * For example, a thread that has called <tt>Object.wait()</tt> * on an object is waiting for another thread to call * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on * that object. A thread that has called <tt>Thread.join()</tt> * is waiting for a specified thread to terminate. */ WAITING, /** * Thread state for a waiting thread with a specified waiting time. * A thread is in the timed waiting state due to calling one of * the following methods with a specified positive waiting time: * <ul> * <li>{@link #sleep Thread.sleep}</li> * <li>{@link Object#wait(long) Object.wait} with timeout</li> * <li>{@link #join(long) Thread.join} with timeout</li> * <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li> * <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li> * </ul> */ TIMED_WAITING, /** * Thread state for a terminated thread. * The thread has completed execution. */ TERMINATED; }
2). 通过 getState() 方法可以获取当前线程的状态
public State getState() { // get current thread state return sun.misc.VM.toThreadState(threadStatus); }
【详细描述】
- NEW(新建状态): 线程对象被创建,还没有调用 start() 方法启动线程。
- RUNNABLE(可运行状态):线程处于可运行状态,可能处于运行中,也可能在像进程一样在等待其他资源,例如 CPU 的调用。
-
BLOCKED(阻塞状态):线程被阻塞等待一个对象的监控锁(monitor lock),以进入同步代码块或同步方法或者重新进入同步代码块或者同步方法。
重入的情况例如:在同步代码块或同步方法中调用 Object.wait 方法后进入等待状态(WAITING), 被唤醒(Object.notify 或 Object.notifyAll)后进入阻塞状态(BLOCKED),需要重新获得对象的监控锁(monitor lock),然后才执行 Object.wait 后面的代码。
- WAITING(等待状态):线程可能因为执行了以下方法而进入等待状态
1). Object#wait(),没有超时设置
2). Thread#join(),没有超时设置
3). LockSupport#park()
一个进入WAITING(等待状态)的线程,需要另外的线程执行特别的动作才能将其唤醒:
1). 一个线程执行了 Object.wait 进入等待状态,则需要另外的线程执行 Object.notify 或 Object.notifyAll 将其唤醒,注意 Object.notify 只会唤醒其中一个等待的线程,具体唤醒哪个是不确定的。
2). 一个线程调用了另外一个线程的 join 方法,等需要等待另外一个线程运行结束,即处于TERMINATED(终止状态),才会被唤醒。
3). 一个线程使用 LockSupport.park 进入等待状态,则另外的线程可以执行 LockSupport.unpark 将其唤醒。
-
TIMED_WAITING(有时间限制的等待状态):线程处于该状态会等待特定时间后被唤醒。线程可能因为执行了以下方法而进入有时间限制的等待状态:
1). Object#wait(long timeout): 参数为毫秒
2). Thread#join(long millis)
3). Thread#sleep(long millis)
4). LockSupport#parkNanos(long nanos)
5). LockSupport#parkUntil(long deadline) -
TERMINATED(终止状态):线程处于终止状态存在两种可能:
1). 线程执行完 run() 方法
2). 执行 run() 方法过程中抛出异常
【测试代码】
/** 1. 创建线程对象 NEW(新建状态):线程对象被创建,还没有调用 start() 方法启动线程 2. 启动线程:调用 start() 方法 RUNNABLE(可运行状态):线程正在等待 CPU 的调用 主线程暂停 100 ms, 让测试线程开始执行 RUNNABLE(可运行状态):线程开始执行 3.主线程先获得 obj 的监控锁(monitor lock), 测试线程进入阻塞状态 BLOCKED(阻塞状态):obj 的监控锁(monitor lock)被 主线程持有, 故测试线程进入阻塞状态, 等待获取 obj 的监控锁 (monitor lock) RUNNABLE(可运行状态):测试线程获得 obj 的监控锁(monitor lock), 执行同步代码块代码 4.测试线程调用 Object#wait() 进入等待状态, 释放 obj 的监控锁(monitor lock) WAITING(等待状态):测试线程需要被唤醒 主线程获得obj 的监控锁(monitor lock), 主线程调用 Object#notifyAll 唤醒等待线程 BLOCKED(阻塞状态):obj 的监控锁(monitor lock)被 main线程持有, 故测试线程进入阻塞状态, 等待获取 obj 的监控锁 (monitor lock) RUNNABLE(可运行状态):测试线程被唤醒, 并重新获得 obj 的监控锁(monitor lock) 5.主线程暂停 100ms, 测试线程暂停 500 ms, 此时测试线程进入有时间限制的等待状态 TIMED_WAITING(有时间限制的等待状态):线程在特定时间的等待后会被唤醒 6.主线程暂停 1000 ms, 等待测试线程执行完成 TERMINATED(终止状态):线程已经执行完成 */ public class Main { public static void main(String[] args) throws InterruptedException { //1. 创建线程对象 System.out.println("1. 创建线程对象"); MyThread t = new MyThread(); System.out.println(t.getState() + "(新建状态):线程对象被创建,还没有调用 start() 方法启动线程"); //2. 启动线程:调用 start() 方法 System.out.println(" 2. 启动线程:调用 start() 方法"); t.start(); System.out.println(t.getState() + "(可运行状态):线程正在等待 CPU 的调用"); //3. 主线程抢先获得 obj 的监控锁 (monitor lock); synchronized (t.obj) { System.out.println("主线程暂停 100 ms, 让测试线程开始执行"); Thread.sleep(100); System.out.println(" 3.主线程先获得 obj 的监控锁(monitor lock), 测试线程进入阻塞状态"); System.out.println(t.getState() + "(阻塞状态):obj 的监控锁(monitor lock)被 main线程持有, 故测试线程进入阻塞状态, 等待获取 obj 的监控锁 (monitor lock)"); } //4.测试线程调用 Object#wait() 进入等待状态, 释放 obj 的监控锁(monitor lock) Thread.sleep(100);//主线程等待 100 ms. 让测试先获得 obj 的监控锁 (monitor lock) System.out.println(t.getState() + "(等待状态):测试线程需要被唤醒"); synchronized (t.obj) { System.out.println("主线程获得obj 的监控锁(monitor lock), 调用 Object#notifyAll 唤醒等待线程"); t.obj.notifyAll(); //如果没有唤醒, 测试线程会一直处于等待状态 System.out.println(t.getState() + "(阻塞状态):obj 的监控锁(monitor lock)被 主线程持有, 故测试线程进入阻塞状态, 等待获取 obj 的监控锁 (monitor lock)"); } //5.主线程暂停 100ms, 测试线程暂停 500 ms, 此时测试线程进入有时间限制的等待状态 Thread.sleep(100); System.out.println(t.getState() + "(有时间限制的等待状态):线程在特定时间的等待后会被唤醒"); //6.主线程暂停 1000 ms, 等待测试线程执行完成 System.out.println(" 6.主线程暂停 1000 ms, 等待测试线程执行完成"); Thread.sleep(1000); System.out.println(t.getState() + "(终止状态):线程已经执行完成"); } } class MyThread extends Thread{ public Object obj = new Object(); @Override public void run(){ //线程开始进行业务处理 System.out.println(getState() + "(可运行状态):线程开始执行"); try { //使线程进入 WAITING (等待状态) synchronized (obj) { System.out.println(this.getState() + "(可运行状态):测试线程获得 obj 的监控锁(monitor lock), 执行同步代码块代码"); //4.测试线程调用 Object#wait() 进入等待状态, 释放 obj 的监控锁(monitor lock) System.out.println(" 4.测试线程调用 Object#wait() 进入等待状态, 释放 obj 的监控锁(monitor lock)"); obj.wait(); System.out.println(this.getState() + "(可运行状态):测试线程被唤醒, 并重新获得 obj 的监控锁(monitor lock)"); } //5.测试线程进入 TIMED_WAITING (有时间限制的等待状态) System.out.println(" 5.主线程暂停 100ms, 测试线程暂停 500 ms, 此时测试线程进入有时间限制的等待状态"); Thread.sleep(500); } catch (InterruptedException e1) { e1.printStackTrace(); } } }