【发布时间】:2011-04-07 19:40:03
【问题描述】:
更新:仍然感到困惑。我认为唯一的可能性是在生成线程后在 init() 方法中引发异常但未记录该异常。我捕获了 create() 方法中抛出的所有异常并将它们记录到警告日志中。任何人都有关于为什么 Log4J 无法打印我的日志消息的理论?日志记录级别设置为 WARN。
我正在 JBoss 上使用 EHCache 运行 Spring 3.0 应用程序。有时当我启动应用服务器时,JVM 会在 20 或 30 秒内完全关闭。我将它设置为每 5 秒进行一次线程转储,并发现在大约 15 秒后,转储开始在同一个线程中呈指数级增长:
"net.sf.ehcache.CacheManager@7d73124b" daemon prio=10 tid=0x00002aac1426a000 nid=0x2300 in Object.wait() [0x00002aac0d886000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00002aaaf5c556e0> (a java.util.TaskQueue)
at java.lang.Object.wait(Object.java:485)
at java.util.TimerThread.mainLoop(Timer.java:483)
- locked <0x00002aaaf5c556e0> (a java.util.TaskQueue)
at java.util.TimerThread.run(Timer.java:462)
到系统关闭时,大约有 10,000 个线程看起来与此完全相同,只是内存地址发生了变化。
我做了一些研究,发现 EHCache 的缓存管理器在 init() 方法中生成了这个线程,该方法由它的每个构造函数调用。缓存管理器应该是一个可以通过 create() 方法访问的单例:
public static CacheManager create() throws CacheException {
if (singleton != null) {
return singleton;
}
synchronized (CacheManager.class) {
if (singleton == null) {
LOG.debug("Creating new CacheManager with default config");
singleton = new CacheManager();
} else {
LOG.debug("Attempting to create an existing singleton. Existing singleton returned.");
}
return singleton;
}
}
每 5 秒进行一次线程转储,当这些线程成倍增加时,我可以看到堆栈跟踪。该同步块中始终存在一个线程,该线程已进入构造函数并将生成一个线程。然后总是有几个线程等待进入同步块。
据我所知,在同步块内对 singleton 进行空检查应该可以防止多个条目进入构造函数,但不知何故,每个线程似乎都在寻找 singleton em> 为空。我将所有异常记录到警告日志中,所以我认为如果在构造函数中创建线程后抛出异常,我会在日志中看到它。我没有看到任何警告,但我证实这会导致这种行为。
有没有人知道如何使多个线程进入该构造函数? java是否会缓存空检查,因为它刚刚对上一行的相同字段进行了空检查?
【问题讨论】:
-
奥卡姆剃刀可能会对你有所帮助
标签: java concurrency ehcache