Я пытался выяснить эту ошибку в течение нескольких дней. Я сузил проблему до тестового примера следующим образом. Опять же, это тестовый пример, который вызывает ошибку. Функция (на данный момент) не является практической, а просто пытается выяснить ошибку.
Сервер работает: - Tomcat 6 - OpenJDK 1.6.0_17 - CentOS 5.5
У меня есть простой файл класса со следующим методом: Статический метод и объявление статической переменной:
public static java.text.SimpleDateFormat displayDateSDF1 = new java.text.SimpleDateFormat("MM/dd/yyyy");
public static java.util.Date getSubDateMini(String inputDate)
{
java.util.Date testObj = null;
try
{
testObj = displayDateSDF1.parse("01/01/2000") ;
}
catch (Exception e)
{
}
return testObj;
}
Тестирование в Tomcat:
Когда я запускаю этот метод, я ожидаю получить тот же результат каждый раз, не так ли? Однако, если я вызываю этот метод из JSP, я получаю ожидаемый результат объекта Date со значением 1/1/2000 около 99,9% времени. Однако иногда я получаю неожиданный объект данных, переданный обратно с кажущимся случайным значением даты.
Чтобы проверить это, я создал JSP со следующим сегментом кода:
for (int i=0; i<200000;i++)
{
java.util.Date testObjLib = TestDate.getSubDateMini("") ;
if (testObjLib!=null&&!testObjLib.toString().equalsIgnoreCase("Sat Jan 01 00:00:00 PST 2000"))
{
out.print("<br>"+testObjLib+"");
}
}
Ниже приведены следующие даты:
Ср. 01.01 00:00:00 PST 1
Пт Авг 01 00:00:00 PDT 2166
В 200 000 прогонов я получаю приблизительно 50 плохих дат, которые дают коэффициент ошибок ~ 0.025%, но опять же случайный. Я запустил этот цикл с 10 итерациями и получил ошибку. Иногда он запускает цикл с 200 000, и все даты выглядят хорошо.
Тестирование в Java:
Выполняя этот цикл через консольное/терминальное приложение в CentOS с тем же циклом, я еще не видел эту ошибку. Я увеличил цикл до 10 000 000 и пока не получил ложных результатов.
Я могу понять из памяти или какую-то заброшенную ошибку (которая приведет к нулевому значению), но не поврежденные/несогласованные данные. Я создал новый сервер с нуля с Tomcat 6, а также попытался Tomcat 5.5, и оба они имеют одинаковые результаты. Я не пробовал Tomcat 7.
Любые предложения?
SimpleDateFormat
не является потокобезопасным.
Это означает, что при доступе к ним из нескольких потоков могут наблюдаться неожиданные результаты. И tomcat обслуживает каждый запрос из отдельного потока, поэтому, когда два запроса выполняются одновременно, проблема возникает.
У вас есть несколько вариантов:
SimpleDateFormat
для каждого вызова метода (а не сделать его static
)ThreadLocal
для его сохранения.DateTimeFormat
является потокобезопасным.