线程状态

原文:https://mp.weixin.qq.com/s/GsxeFM7QWuR--Kbpb7At2w

人类为了利用好自己的时间,经常会同时做多件事情,比如上厕所时刷手机,开车时听新闻... 对于自己尚且如此,对计算机也不能闲着。为了最大化的提升机器利用率,机器上同时会跑许多的服务,每个服务内,又跑着许多的「线程」。

 

这些线程奔忙在一线,努力的执行着「老大」交给自己的任务。偶有空闲时间,打个小盹。

 

经常会有人问类似这样的问题:

 

Q: 应用程序响应特别慢。不知道是什么原因。

A: 用 jstack 分析下应用的线程在干啥  (具体使用可以参考:Java 线程状态分析工具jstack

Q: 打出来,这该怎么看呢?

A: 找应用具体执行业务逻辑的线程,看状态

Q: 有BLOCKED,有WAITING,不知道怎么看,看到有一段业务好像在取资源

A: ...资源阻塞了

 

这类问题,我们首先需要了解线程这些状态分别代表什么,这些状态之间,又是如何迁移变换的。

 

正好最近群里有人在问类似的问题,总结下方便有需要的朋友。

 

 线程的状态与转换

 

以 Java 语言为例,在语言初期就提供了创建多线程的能力。这些勤劳的线程,一生会经历多种状态

 

  • NEW

  • RUNABLE

  • TIMED_WAITING

  • WAITING

  • BLOCKED

  • TERMINATED

 

当前一个线程的的具体状态,通过Thread的 State 反映。通过这些状态,可以让「老大」了解到线程处于什么阶段。同时,对于我们开发者问题的诊断分析,也有很大的指导意义。

 

 

我们来看下面这张图,清晰的展示了线程状态的之间的变换过程。

 

 

比如我们较常见的 BLOCKED状态,一般都是在请求锁,在请求资源之类的。比如多线程操作数据库,一个耗时较多的操作,会导致其他对于库的写入也受影响。

 

再比如操作系统等限制了可以打开的文件句柄数,如果系统里已经打开达到了阈值,但未进行正确的关闭,此时就会产生问题。 这里需要注意的是,一些云服务器,云盘服务,对象存储等,也会对应的占用一个资源。我之前就在使用云服务的对象存储时,排查过类似的关闭问题。

 

TIME_WAITING 一般则是处于sleep方法,wait方法,join等操作,正在等待时间

 

RUNNABLE 一般都是你最喜欢看到的,在努力干着活的线程。

 

如何了解当前线程状态

 

我们前面提到,为了了解线程当前的执行状态,需要通过 jstack 工具来获取线程的 stack 信息,再从中找到我们关心的线程具体的执行情况。

 

这里首先需要关注的一点是,对于我们自己的线程,一定要「给他一个名字」。否则,在茫茫的线程海里,你只能欲哭无泪。

 

对于通过 Thread 创建线程时,可以直接通过构造方法指定名称。 通过「线程池」来获取线程,需要定义自己的ThreadFactory,在其中指定生成的线程名字。

 

你说我使用 ExecutorService,这个默认生成的线程池,使用的都是默认的 ThreadFactory,结果名字都是这个样子:

 

DefaultThreadFactory() {
    SecurityManager s = System.getSecurityManager();
    group = (s != null) ? s.getThreadGroup() :
                          Thread.currentThread().getThreadGroup();
    namePrefix = "pool-" +
                  poolNumber.getAndIncrement() +
                 "-thread-";
}

 

如果线程多的话,全是 pool-x-thread-x 这个样子,你也需要具体定位。

 

有了具体名字之后,在jstack 生成的信息中,就可以直接定位我们关注的线程了。

 

比如通过jstack看到这样的信息:

 

 

此时,看到显眼的 BLOCKED 再分析是否是代码的问题

 

当然,在Linux环境中,也可以搭配置 「top」命令来分析。具体可以按这个步骤来操作:

 

  1. 先用top 命令在机器上分析出当前占用cpu的进程,

  2. 通过top -H -p <pid>  查看进程内各个线程的资源占用

  3. 第一列显示的是这些线程的pid,此时再搭配 jstack生成的线程 stack信息查找对应的内容。需要注意一点,这里得先把pid转换成十六进制,然后再搜索即可,对应我们上面内容中的nid

 

当然,除此之外,类似于 JConsole、JVisualVM 这些工具中都有关于线程的列表,本质上也和 jstack信息一致,不过是有显眼的颜色状态显示。

 

通过这些工具,来更详细的分析线程的工作情况,在问题产生的时候,可以做到有的放矢。

 

PS: 对于 jstack 工具的使用,可以间隔一小段时间多次打印,对比分析,发现问题。

 

图片来源(https://www.uml-diagrams.org/examples/java-6-thread-state-machine-diagram-example.html)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值