我已经解压缩了我的容器进程的JStack,并使用Thread.state
分组的以下分布获得了运行的线程:
count thread state
67 RUNNABLE
1 TIMED_WAITING (on object monitor)
8 TIMED_WAITING (parking)
4 TIMED_WAITING (sleeping)
3 WAITING (on object monitor)
17 WAITING (parking)
对于可运行的线程,我有以下描述:
"http-bio-8080-exec-55" daemon prio=10 tid=0x000000002cbab300 nid=0x642b in Object.wait() [0x00002ab37ad11000]
java.lang.Thread.State: RUNNABLE
at com.mysema.query.jpa.impl.JPAQuery.<init>(JPAQuery.java:44)
at net.mbppcb.cube.repository.TransactionDaoImpl.findByBusinessId(TransactionDaoImpl.java:73)
at sun.reflect.GeneratedMethodAccessor76.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:155)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
...
如上所示,处于RUNNABLE状态的线程数会随着时间的推移而增加,而且似乎是挂起的。如果他们认为被阻止,他们不应该处于阻塞状态吗?或者他们应该处于WAITING状态?拥有RUNNABLE线程但在Object.wait()中是不是很奇怪?
更新1
我可以在文档中看到:
处于runnable状态的线程正在Java虚拟中执行 机器,但它可能正在等待操作中的其他资源 系统,如处理器。
我怎样才能弄清楚等待的线程是什么?
答案 0 :(得分:20)
这似乎是class initialization deadlock。
JPAQuery
构造函数正在等待依赖类的初始化,可能是JPAProvider
:
public JPAQuery(EntityManager em) {
super(em, JPAProvider.getTemplates(em), new DefaultQueryMetadata());
}
当从静态初始化程序引用子类时,此类死锁可能由typical bug引起。如果您共享其他线程堆栈的详细信息,我们可能会找出哪个线程持有类锁。
为什么线程处于RUNNABLE
状态呢?
嗯,这是HotSpot JVM内部的混乱。类初始化过程在VM运行时实现,而不是在Java域中实现,并且类锁是本机获取的。似乎是线程状态未被更改的原因,但我想这种行为也应该在JVM中修复。
答案 1 :(得分:3)
Oracle Thread.State documentation指定处于阻塞状态的线程正在等待监视器锁定以进入同步块/方法或在调用后重新输入同步块/方法。 在阻塞模式下看起来没有任何线程。
答案 2 :(得分:1)
如果在数据库操作中显然阻止了所有Runnable线程,我建议使用数据库监视/诊断工具来探索原因。之后,可能会调查您的数据库代码,以查找未提交的事务,导致未关闭资源的错误处理异常等问题。
Java线程转储可能已经为您提供了他们此时可以获得的所有信息 - 指示下一步开始查看的位置。
答案 3 :(得分:0)
&#34;如上所示处于RUNNABLE状态的线程数随之增加 时间,似乎是悬挂。&#34;
RUNNABLES的数量会增加,具体取决于执行方法的线程数&#34; com.mysema.query.jpa.impl.JPAQuery。&#34;在这个线程转储被采取时。此方法实际上是JPAQuery类的构造函数 - 由&#34; init&#34; 表示。您可能需要调查构造函数中的代码以及后续对JPA实现的调用。
答案 4 :(得分:0)
Object.wait()
只调用Object.wait(0)
(零没有超时)。
Object.wait(long)
的实施是:
public final native void wait(long timeout) throws InterruptedException;
本机框架中的所有线程都是RUNNABLE
,因为JVM不知道(不管理&#34;因此它是&#34;本机&#34;帧)电话的状态。