У меня возникла странная проблема в одном из наших проектов. Мы используем JUnit для запуска наших модульных тестов, и некоторое время назад мы начали параллельно запускать пробные тесты, чтобы ускорить выполнение. В большинстве случаев все в порядке, но время от времени почти все наши тесты терпят неудачу. В следующем прогоне все они проходят снова без изменения кода.многопотоковые и статические блоки
Ошибки, по-видимому, указывают на то, что некоторые статические экземпляры не инициализируются правильно или не используются до завершения инициализации в многопоточном случае. (Я не могу отладить это, так как проблема никогда не появлялась при отладке ->Heisenbug.)
Извините, я не могу предоставить минимальный рабочий пример, показывающий ошибку, поскольку она исчезает при попытке воспроизведения.
Конкретный вопрос: при объявлении переменной, как показано ниже, существует ли вероятность того, что инициализация a или b не завершилась, когда foo() или bar() вызываются другим потоком? Я думал, что статический блок будет гарантированно выполняться до того, как любой из методов будет вызван. Или могут возникнуть проблемы с загрузкой классов? Или известные ошибки в JRE (мы в настоящее время застряли на 1.6.0_21, новые версии еще не предоставлены нашим ИТ-отделом)?
class C {
private static final A a;
private static final B b;
static {
a = new A(...);
b = new B(...);
}
public static void foo() {
useA();
}
public static void bar() {
useB();
}
}
Я уверен, что это не связано с оборудованием, поскольку оно появляется на разных машинах разных производителей. Тесты используют сервер vm.
Спасибо,
Axel
«new A()' или 'new B()' запускать новые потоки? Вы пытались изолировать проблему и создать [SSCCE] (http://sscce.org), который воспроизводит проблему? – assylias
Как я знаю, это плохая практика использования целого класса со статическими полями и методами, особенно при многопоточности. Почему бы вам не создать нестатический класс и сохранить его в статическом поле? – alaster
Вот что делается здесь. a и b являются экземплярами классов, которые обеспечивают заранее рассчитанные значения. Оба класса неизменяемы и имеют методы, которые возвращают эти предварительно рассчитанные значения. Вычисления выполняются в конструкторах соответствующих классов. При доступе имеется не более чем проверка аргументов, вычисление индекса и возврат элемента массива, содержащего ранее вычисленное значение. – Axel