一个 Java 线程对应一个本地 native 线程, 本地线程才是真实的线程实体.

    pstack
    获得 JVM 本地线程的堆栈

    线程状态 Runnable 是从 JVM 角度来看的, 表示这个线程正在运行.
    但是处于 Runnable 状态的线程不一定真的消耗 CPU, 只能说明线程没有阻塞在 Java 的 wait() 或者 sleep() 方法上, 同时也没有在锁上面等待.
    但是如果该线程调用了本地方法, 而本地方法处于等待状态, 这时 JVM 并不知道本地代码发生了什么, 此时尽管线程实际是阻塞状态, 但显示的是 Runnable 状态, 这种情况是不消耗 CPU 的, 如 socket IO.
    因此分析哪个线程在大量消耗 CPU, 不能以 Runnable 这个词作为判断依据.

    与锁相关的信息

    • 当一个线程占有一个锁时, 线程堆栈打印 locked <>
    • 当一个线程等待其他线程释放锁时, 线程堆栈打印 waiting to lock <>
    • 当一个线程占有一个锁, 又执行该锁的 wait() 方法时, 线程堆栈先打印 locked <>, 再打印 waiting on <>

    image.png
    image.png
    image.png