一般而言线程从创建到运行结束有五个状态:新建、就绪、运行、阻塞、死亡


java多线程的结束进程 java多线程状态_性能瓶颈



java线程状态可以通过调用相应Thread实例的getState方法获取,通过源码可以看到该方法的返回值是一个枚举类型,Thread.State所定义的线程状态包括以下几种

NEW  :一个刚创建而未启动的线程处于该状态。一个线程只有一次处于该状态
RUNNABLE  :该状态可以看成一个复合状态。它包括两个子状态:READY和RUNNING。前者表示该状态的线程可以被JVM的线程调度器(Scheduler)进行调度而使之处于RUNNING状态。后者表示该线程正在运行。当Thread实例的yield方法被调用或者由于线程调度器的原因,相应的线程状态会由RUNNING转换为READY。
BLOCKED  :一个线程发起一个阻塞式I/O操作(如文件读写和阻塞式Socket读写)后,或者试图去获得一个由其他线程持有的锁时,相应的线程就会处于该状态。
WAITING  :一个线程执行了某些特定的方法就会处于这种无限等待其他线程执行特定操作的状态。这些方法包括:Object.wait()、LockSupport.park()和Thread.join()。
TIMED_WAITING  :和WAITING类似,区别就是加上等待时间。
TERMINATED  :已执行结束的线程处于该状态。

了解线程状态的作用用一句话 概括就是 帮助找到系统中的潜在性能瓶颈 .

当java系统运行慢的时候, 我们想到的应该先找到性能的瓶颈, 而jstack等工具, 通过jvm当前的stack可以看到当前整个vm所有线程的状态, 当我们看到一个线程状态经常处于

WAITING 或者 BLOCKED的时候, 要小心了, 他可能在等待资源经常没有得到释放(当然, 线程池的调度用的也是各种队列各种锁, 要区分一下, 比如下图)


java多线程的结束进程 java多线程状态_线程状态_02


这是个经典的并发包里面的线程池, 其调度队列用的是LinkedBlockingQueue, 执行take的时候会block住, 等待下一个任务进入队列中, 然后进入执行, 这种理论上不是系统的性能瓶颈, 找瓶颈一般先找自己的代码stack,再去排查那些开源的组件/JDK的问题

排查问题的几个思路:

0. 如何跟踪一个线程?

看到上面的stack输出没有, 第一行是内容是 threadName priority tid nid desc

更过跟踪tid, nid 都可以唯一找到该线程.

1. 发现有线程进入BLOCK, 而且持续好久, 这说明性能瓶颈存在于synchronized块中, 因为他一直block住, 进不去, 说明另一个线程一直没有处理好, 也就这个synchronized块中处理速度比较慢, 然后再深入查看. 当然也有可能同时block的线程太多, 排队太久造成.

2. 发现有线程进入WAITING, 而且持续好久, 说明性能瓶颈存在于触发notify的那段逻辑. 当然还有就是同时WAITING的线程过多, 老是等不到释放.

3. 线程进入TIME_WAITING 状态且持续好久的, 跟2的排查方式一样.