Наводнение потоков EHCache, порожденных при запуске

#java #concurrency #ehcache

#java #параллелизм #ehcache

Вопрос:

ОБНОВЛЕНИЕ: Все еще озадачен. Я думаю, что единственная возможность заключается в том, что исключение генерируется внутри метода init() после создания потока, но исключение не регистрируется. Я перехватываю все исключения, генерируемые методом create(), и регистрирую их в журнале предупреждений. У кого-нибудь есть теория о том, почему Log4J не сможет печатать мои сообщения журнала? Уровень ведения журнала установлен на ПРЕДУПРЕЖДЕНИЕ.

Я запускаю приложение Spring 3.0, используя EHCache на JBoss. Иногда, когда я запускаю сервер приложений, 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 секунд, я могу видеть трассировки стека по мере размножения этих потоков. Внутри этого блока синхронизации всегда есть один поток, который добрался до конструктора и создаст поток. Тогда всегда есть несколько потоков, ожидающих попадания в синхронизированный блок.

Насколько я могу судить, эта проверка null для синглтона внутри синхронизированного блока должна предотвращать более одной записи в конструктор, но каким-то образом каждый поток, похоже, находит, что синглтон равен null. Я регистрирую все исключения в журнале предупреждений, поэтому я думаю, что если бы исключение создавалось после того, как поток был создан в конструкторе, я бы увидел это в журнале. Я не вижу никаких предупреждений, но я проверил, что это могло бы вызвать такое поведение.

У кого-нибудь есть какие-либо другие идеи, как более одного потока могли бы перейти к этому конструктору? Будет ли java кэшировать проверку null, поскольку она только что проверила null то же поле в предыдущей строке?

Комментарии:

1. Бритва Оккама, вероятно, помогла бы вам

Ответ №1:

Глядя на дамп потока, кажется, что реальной проблемой может быть неисправный таймер, который постоянно порождает потоки, которые обращаются к менеджеру кэша. Думаю, я бы сначала проверил ваш код, чтобы убедиться, что вы не запускаете таймер со временем ожидания 0 (это может быть результатом неправильного вычисления временного смещения).

Комментарии:

1. Даже если существовал таймер, постоянно обращающийся к менеджеру кэша, он реализован как синглтон. Вы должны иметь возможность обращаться к нему столько раз, сколько вам нужно.

Ответ №2:

Если это потоки, порожденные инициализацией менеджера кэша, то, вероятно, это потоки, следящие за обновлением версии на сайте ehcache (хотя я не могу быть уверен). Эти проверки могут быть подавлены либо с помощью свойства времени выполнения Terracotta (я не помню его названия), либо с помощью настройки конфигурации кэша (какой-либо атрибут XML или установщик Spring, в зависимости от того, как определена конфигурация кэша).

Комментарии:

1. Спасибо, но я уже отключил средство проверки обновлений. Это поток, который будет проверять наличие обновлений, но он не указывает на то, как создается так много.

2. Я не знаю, почему так много (никогда такого не было). Но если это поток проверки обновлений, то я думаю (опять же, не уверен), вы можете заблокировать его «создание» (у меня такое ощущение, что один из этих 2 настроек, которые я упомянул в моем ответе, применяется поздно, уже после создания потока).

Ответ №3:

Попытка создать существующий синглтон. Возвращен существующий синглтон.