线程转储显示Runnable状态,但它挂了很长时间

时间:2012-01-23 05:54:31

标签: java

我们的应用程序遇到了一个不寻常的问题,在过去的一个月里,我们的应用程序达到了不可恢复的状态,在应用程序重启后恢复了。

背景:我们的应用程序进行数据库查询以获取一些信息,并且此数据库托管在单独的节点上。

有问题的情况:当分析线程转储时,我们看到所有线程都处于可运行状态,从数据库中获取数据,但即使在20分钟后它也没有完成。

按预期发布应用程序重启所有线程都已恢复。 CPU使用率也很正常。

以下是线程转储

  

ThreadPool:2:47“prio = 3 tid = 0x0000000007334000 nid = 0x5f runnable   [0xfffffd7fe9f54000] java.lang.Thread.State:RUNNABLE at   oracle.jdbc.driver.T2CStatement.t2cParseExecuteDescribe(Native方法)     在   oracle.jdbc.driver.T2CPreparedStatement.executeForDescribe(T2CPreparedStatement.java:518)     在   oracle.jdbc.driver.T2CPreparedStatement.executeForRows(T2CPreparedStatement.java:764)     在ora

All threads in the same state.

问题:

  1. 这个州可能是什么原因?
  2. 在这种情况下如何恢复?

5 个答案:

答案 0 :(得分:1)

它可能正在等待来自数据库服务器的网络数据。 JVM将I / O上等待(阻塞)的Java线程描述为处于RUNNABLE状态,即使从程序的角度来看它们也被阻止了。

答案 1 :(得分:1)

正如其他人已经提到的那样,本机方法总是处于可运行状态,因为JVM并不知道/关心它们。

默认情况下,客户端的Oracle驱动程序没有套接字超时。这意味着如果您遇到网络问题,客户端的低级套接字可能会卡住"永远存在,导致maxxed out连接池。您还可以检查到Oracle服务器的网络流量,看它是否甚至传输数据。

使用瘦客户端时,您可以设置oracle.jdbc.ReadTimeout,但我不知道如何为您使用的胖(oci)客户端执行此操作,我不熟悉它。

怎么办?研究如何为thick ojdbc驱动程序指定读取超时,并观察与连接超时相关的异常,这将清楚地表明网络问题。如果您可以更改源,则可以在捕获与超时相关的SQLExceptions时包装调用并重试会话。

要快速解决问题,请手动终止Oracle服务器上的连接。

值得检查会话争用,可能是查询会阻止这些会话。如果找到一个,您将看到哪个数据库对象导致问题。

答案 2 :(得分:0)

本机方法始终处于RUNNABLE状态(好吧,除非您从本机方法本身更改状态,但这不计算在内)。

该方法可以在IO上阻止,任何其他事件等待或只是长cpu密集的任务...或无限循环。 你可以自己挑选。

  

在这种情况下如何恢复?

从oracle中删除连接。

答案 3 :(得分:0)

系统或JVM是否被绞死? 如果可配置,如果可能,减少线程/并行连接的数量。

线程在等待IO时只会浪费CPU周期。 是的,您的CPU很快就被等待DB响应的线程忙碌了。

答案 4 :(得分:0)

  1. 您的代码是否手动处理交易?如果那时,也许某些代码在更改数据后没有提交()。或者有人直接通过PLSQL或其他东西运行数据修改查询但没有提交,这导致所有读取操作都被挂起。

  2. 当您遇到“挂起”并且数据库已从状态恢复时,您是否检查了数据是否已回滚?询问此问题,因为您说“应用程序重启后恢复了”。当JDBC驱动程序更改了东西但没有提交,并且发生超时时,就会发生这种情况......数据库操作将被回滚。 (虽然可以根据配置而有所不同)