2017-02-13 24 views
0

Я поддерживаю код Java 1.6, где выполняется сравнение даты.Иногда java.util.Date перед сбоем

static final SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy"); 

static void process(Message message) { 
String now =formatter.format(new Date()); 
String end = formatter.format("01-12-2017"); 

Date endDay = formatter.parse(end); 
Date currentDay = formatter.parse(now); 

if(endDay.before(currentDay)){ 
    System.out.println("Send a notification indicating the end day has been reached, so the message is not processed."); 
}else { 
    System.out.println("Process the message and applies some business rules"); 
} 
} 

Я знаю, что код не самый лучший, но из 160000 сделок 3 потерпели неудачу, и код в блоке, если выполняется. Я планирую использовать Календарь, но что могло бы произойти здесь?

+0

Если вы можете использовать Java 8 'java.time. *' Я настоятельно рекомендую. – Simon

+0

Спасибо, Саймон, я поддерживаю платформу Java 1.6. – mlavarreda

+0

Тогда, возможно, время в Joda - это вариант – Simon

ответ

3

Т.Л., д-р

Используйте поточно-java.time классы вместо резьбовых небезопасным наследство SimpleDateFormat класса.

DateTimeFormatter f = DateTimeFormatter.ofPattern("MM-dd-uuuu") ; 
ZoneId z = ZoneId.of("America/Montreal") ; 
… 
LocalDate.parse("01-12-2017" , f) 
     .isBefore(LocalDate.now(z)) 

Устаревшие классы даты и времени не поточно-

Я заметил, что вы используете singleton для форматере, один статический экземпляр SimpleDateFormat. Это legacyкласс неthread-safe, как описано в классе JavaDoc:

Синхронизация

Дата форматы не синхронизированы. Рекомендуется создавать отдельные экземпляры формата для каждого потока. Если несколько потоков обращаются к формату одновременно, его необходимо синхронизировать извне.

Ваш отчет о случайной ошибке, по всей видимости, не имеет веской причины, подсказывает мне, что вы используете этот объект из более одного потока за раз. Статический метод с именем process, и ваше упоминание в комментариях сервера делает меня еще более подозрительным. Время от времени во время выполнения вы сталкиваетесь с столкновением потоков.

Избегайте устаревших классов времени.

Вы используете неприятные старые классы времени, которые теперь legacy, вытесненные классами java.time. Большая часть функциональных возможностей java.time обратно переносится на Java 6 & 7 в ThreeTen-Backport.

Классы java.time используют immutable objects и предназначены для обеспечения потокобезопасности. Так говорит package documentation.

LocalDate

Вы используете объекты даты и времени для даты только значения. Классы java.time включают способ представления даты только. Класс LocalDate представляет собой значение даты только без времени и без часового пояса.

Часовой пояс имеет решающее значение для определения даты.В любой данный момент дата изменяется по всему миру по зонам. Например, через несколько минут после полуночи в Paris France - это новый день, пока еще «вчера» в Montréal Québec.

Указать proper time zone name в формате continent/region, такие как America/Montreal, Africa/Casablanca или Pacific/Auckland. Никогда не используйте аббревиатуру 3-4 буквы, такую ​​как EST или IST, так как они не настоящие часовые пояса, не стандартизированные, и даже не уникальные (!).

Класс ZoneId является потокобезопасным. Таким образом, вы можете сохранить экземпляр для повторного использования в потоках.

ZoneId z = ZoneId.of("America/Montreal"); 
LocalDate today = LocalDate.now(z); 

При представлении даты как строки, я предлагаю использовать стандартные ISO 8601 форматы. Только для даты только ГГГГ-ММ-ДД, например 2017-01-23. Классы java.time используют эти стандартные форматы по умолчанию при разборе/генерации строк.

LocalDate target = LocalDate.parse("2017-01-23"); 

Если формат находится вне вашего контроля, используйте DateTimeFormatter, как показано во многих других вопросах & ответы на переполнение стека. Этот класс является потокобезопасным, поэтому вы можете сохранить экземпляр для повторного использования в потоках.

DateTimeFormatter f = DateTimeFormatter.ofPattern("MM-dd-uuuu"); 
LocalDate target = LocalDate.parse("01-12-2017" , f); 

Сравнение с такими методами, как isEqual, isBefore и isAfter.

if(target.isBefore(today)){ 
    System.out.println("Send a notification indicating the end day has been reached, so the message is not processed."); 
} else { 
    System.out.println("Process the message and applies some business rules"); 
} 

О java.time

java.time каркас встроен в Java 8 и более поздних версий. Эти классы вытесняют неприятные старые legacy классы времени, такие как java.util.Date, Calendar, & SimpleDateFormat.

Проект Joda-Time, в настоящее время в maintenance mode, советует перейти на классы java.time.

Чтобы узнать больше, см. Oracle Tutorial. И поиск Stack Overflow для многих примеров и объяснений. Спецификация: JSR 310.

Где получить классы java.time?

  • Java SE 8 и SE 9, а затем
    • Встроенный.
    • Часть стандартного Java API с объединенной реализацией.
    • Java 9 добавляет некоторые незначительные функции и исправления.
  • Java SE 6 и SE 7
    • Большая часть Явы.временная функциональность обратно перенесена на Java 6 & 7 в ThreeTen-Backport.
  • Android
+0

Большое спасибо за ваш полный и подробный ответ !!. Вы были абсолютно правы, проблема заключалась в использовании небезопасного SimpleDateFormat. Я выполняю тест, создающий пул потоков Executor из 5 потоков, и я смог воспроизвести ошибку. – mlavarreda

0

Вы видите Javas Date библиотека, как известно, не лучшая работа для работы с датами. Особенно, когда мы говорим о java-1.6.

Мое предложение для вас связаться с этим Joda Time. Here вы можете найти все, что вам нужно для библиотеки. В моем личном опыте он работает более стабильно, и его легко понять.

+3

На самом деле это не задает вопрос. Конечно, Joda Time - лучший API, но 'Date.before()' работает сам по себе. Это было бы уместно в качестве комментария, который я знаю, что вы не можете добавить себя, но есть уже комментарии, предлагающие использовать Joda Time. –

+0

Yep, Date.before() работает. Проблема была SimpleDateFormat как singleton. – mlavarreda

 Смежные вопросы

  • Нет связанных вопросов^_^