Java线程状态

发布时间 2023-09-04 22:45:10作者: 无以铭川

Java线程状态

Java 中有六个线程状态:

// Thread.State
public enum State {
    NEW,
    RUNNABLE,
    BLOCKED,
    WAITING,
    TIMED_WAITING,
    TERMINATED;
}

这些线程状态表示线程的生命周期, 其状态变化图如下:

线程生命周期

NEW

每个线程在新建之后, 调用 start 方法前, 都处于 NEW 状态.

start 方法本身并不修改线程状态, 而是其中调用的 start0native 方法, 在 jdk 的源码中最终调用了下面这段代码修改的线程状态:

void Thread::start(Thread* thread) {
  // Start is different from resume in that its safety is guaranteed by context or
  // being called from a Java method synchronized on the Thread object.
  if (thread->is_Java_thread()) {
    // Initialize the thread state to RUNNABLE before starting this thread.
    // Can not set it after the thread started because we do not know the
    // exact thread state at that time. It could be in MONITOR_WAIT or
    // in SLEEPING or some other state.
    java_lang_Thread::set_thread_status(JavaThread::cast(thread)->threadObj(),
                                        JavaThreadStatus::RUNNABLE);
  }
  os::start_thread(thread);
}

RUNNABLE

start 之后, 线程状态就变为了 RUNNABLE, RUNNABLE 不代表线程正在运行, 也可能是在等待CPU或IO资源.

例如:

public class Test {
    public static void main(String[] args) throws Exception {
        System.in.read();
    }
}

System.in.read() 将让线程暂停运行直到控制台输入任何字符, 但此时通过 jstack 观察到线程状态是 RUNNABLE.

"main" #1 [16836] prio=5 os_prio=0 cpu=796.88ms elapsed=31.46s tid=0x0000022a267f19d0 nid=16836 runnable  [0x000000ec5d2ff000]
   java.lang.Thread.State: RUNNABLE
Thread: 0x0000022a267f19d0  [0x41c4] State: _at_safepoint _at_poll_safepoint 0
   JavaThread state: _thread_in_native
	at java.io.FileInputStream.readBytes(java.base/Native Method)
	at java.io.FileInputStream.read(java.base/FileInputStream.java:287)
	at java.io.BufferedInputStream.fill(java.base/BufferedInputStream.java:291)
	at java.io.BufferedInputStream.implRead(java.base/BufferedInputStream.java:325)
	at java.io.BufferedInputStream.read(java.base/BufferedInputStream.java:312)
	at Test.main(Test.java:4)

BLOCKED

处于 BLOCKED 状态的线程正在等待取得锁.

当线程进入 sychronized 代码块/方法, 或调用 Object.wait() 后重新进入 synchronized 代码块/方法的时候, 会处于阻塞状态.

Java 线程的 BLOCKED 状态与一般所说的阻塞存在一定区别, BLOCKED 状态仅代表Java 线程在等待取得锁, 而一般所说的阻塞通常指线程暂停运行, 即上文中提到的System.in.read() 导致的线程暂停运行等待IO的情况在很多时候也称之为阻塞. 为避免歧义, 下文中的阻塞指线程暂停运行.

WAITING

处于 WAITING 状态的线程等待其它线程的通知.

调用 Object.wait, Thread.join, LockSupport.park 会导致线程进入 WAITING 状态, 对应的需要调用 Object.notifyObject.notifyAll, 线程终止, LockSupport.unpark 解除线程的 WAITING 状态. WAITING 状态解除的线程并不一定会变为 RUNNABLE 状态, 如 Object.wait 的线程会变为 BLOCKED 状态直到取得锁才能变为 RUNNABLE.

TIMED_WAITING

逻辑同 WAITING, 不同在于等待一定时间后没有通知就自动恢复.

相关的调用有:

  • Thread.sleep
  • Object.wait(long timeout)
  • Thread.join(long timeout)
  • LockSupport.parkNanos
  • LockSupport.parkUntil

测试

下面这段代码输出线程不同的状态

public class Main {

  private static Thread thread1 = null;
  private static Thread thread2 = null;

  public static void main(String[] args) throws InterruptedException {
    thread1 = new Thread(() -> {
      // RUNNABLE
      System.out.println("Thread1 running state: " + thread1.getState());
      try {
        // 等待一会, 让thread2取得锁
        Thread.sleep(1000);
      }
      catch (InterruptedException e) {
        throw new RuntimeException(e);
      }
      synchronized (Main.class) {
        // thread1 取得锁, 此时thread2 调用了 Object.wait()
        System.out.println("Thread2 Object.wait() state: " + thread2.getState());
        // 唤醒thread2
        Main.class.notify();
        // thread2 从等待状态被唤醒, 接着等待锁
        System.out.println("Thread2 wait lock state: " + thread2.getState());
      }
    });
    System.out.println("Thread1 new state: " + thread1.getState());
    thread2 = new Thread(() -> {
      synchronized (Main.class) {
        // thread1 正在sleep
        System.out.println("Thread1 sleep state: " + thread1.getState());
        try {
          // thread1 等待锁
          Thread.sleep(1000);
          System.out.println("Thread1 acquiring lock state: " + thread1.getState());
        }
        catch (InterruptedException e) {
          throw new RuntimeException(e);
        }
        try {
          // 让出锁, 让thread1 执行
          Main.class.wait();
          // thread1 执行完, thread2 取得锁恢复执行
        }
        catch (InterruptedException e) {
          throw new RuntimeException(e);
        }
      }
      // thread1 已经结束
      System.out.println("Thread1 run out state: " + thread1.getState());

    });
    thread1.start();
    // 保证thread1先执行
    Thread.sleep(500);
    thread2.start();
  }
}

输出:

Thread1 new state: NEW
Thread1 running state: RUNNABLE
Thread1 sleep state: TIMED_WAITING
Thread1 acquiring lock state: BLOCKED
Thread2 Object.wait() state: WAITING
Thread2 wait lock state: BLOCKED
Thread1 run out state: TERMINATED