线程阻塞排除

发布于:2025-02-15 ⋅ 阅读:(88) ⋅ 点赞:(0)

例子

例如这种情况,假如java用@Scheduled 注解标识了一个定时任务,这定时任务会去调用第三方接口,有天这个第三方接口挂了,这里也没有做任何处理,相当于一直在等待第三方接口响应,导致其他定时任务无法调度,如果我不知道是这种情况的前提下我怎么排除呢

使用 jstack 或 VisualVM 检查线程状态

jstack:你可以通过 jstack 获取当前线程的堆栈信息。如果你怀疑某个线程(例如定时任务的线程)处于阻塞状态,可以通过 jstack 输出线程堆栈,查看是否有线程被 wait、block 或处于 BLOCKED 状态。

先使用jps获取pid,再用jstack分析


jstack <PID> > thread_dump.txt

通过分析堆栈信息,检查是否有定时任务的线程卡在等待外部接口的响应。如果是阻塞在网络调用上,堆栈中应该会显示类似 SocketInputStream.read() 或其他阻塞网络相关的栈帧。

案例

使用jstack查看到如下信息
我们可以看到线程卡在了 com.example.ExternalApiClient.callApi(ExternalApiClient.java:30) 这个代码行。这个信息直接告诉我们,在 ExternalApiClient 类的第 30 行调用了外部 API,但是由于某些原因(可能是网络问题或外部 API 延迟),该线程一直等待响应,没有释放。

"thirdPartyApiCaller" #18 prio=5 os_prio=0 tid=0x00007f07e32a4800 nid=0x1c14 waiting for I/O [0x00007f07e352d000]
   java.lang.Thread.State: WAITING (on I/O)
       at java.net.SocketInputStream.socketRead0(Native Method)
       at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
       at java.net.SocketInputStream.read(SocketInputStream.java:170)
       at java.net.SocketInputStream.read(SocketInputStream.java:141)
       at sun.security.ssl.InputRecord.readFully(InputRecord.java:465)
       at sun.security.ssl.InputRecord.read(InputRecord.java:503)
       at sun.security.ssl.SSLSocketImpl.readApplicationRecord(SSLSocketImpl.java:1055)
       at sun.security.ssl.SSLSocketImpl$AppInputStream.read(SSLSocketImpl.java:1130)
       at com.example.ExternalApiClient.callApi(ExternalApiClient.java:30)

总结

使用


网站公告

今日签到

点亮在社区的每一天
去签到