启动时产生的EHCache线程泛滥

时间:2011-04-07 19:40:04

标签: java concurrency ehcache

更新:仍然困惑。我认为唯一的可能性是在生成线程之后在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秒进行一次线程转储,我可以在这些线程相乘时看到堆栈跟踪。同步块中总有一个线程已经使它成为构造函数并将生成一个线程。然后总有几个线程等待进入同步块。

据我所知,对synchronized块中的 singleton 进行空检查应该会阻止多个条目进入构造函数,但不知何故,每个线程似乎都在找 singleton 为null。我记录了警告日志的所有异常,所以我想如果在构造函数中创建线程后抛出异常,我会在日志中看到它。我没有看到任何警告,但我确认这会导致这种行为。

有没有人知道多个线程如何才能使它成为该构造函数? java会缓存null检查,因为它只检查了前一行上的相同字段吗?

3 个答案:

答案 0 :(得分:0)

查看线程转储,看起来真正的问题可能是计时器运行错误,它不断产生访问缓存管理器的线程。我想我首先检查一下你的代码,以确认你没有使用0等待时间来触发计时器(可能是计算错误时间偏差的结果)。

答案 1 :(得分:0)

如果这是由缓存管理器的init生成的线程,那么他们可能是在ehcache站点上观察版本更新的线程(虽然我不能确定)。可以使用Terracotta的运行时属性(我不记得它的名称)或缓存配置设置(某些XML属性或Spring setter,取决于如何定义缓存配置)来抑制这些检查。

答案 2 :(得分:-2)

尝试创建现有的单身人士。现有的单身人士返回。