Java线程状态

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

作者:无以铭川

出处:https://www.cnblogs.com/wymc/p/17678210.html

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   无以铭川  阅读(25)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
点击右上角即可分享
微信分享提示
more_horiz
keyboard_arrow_up light_mode palette
选择主题
menu