Пользовательский конвертер JSF для даты - потокобезопасен ли?

StackOverflow https://stackoverflow.com/questions/4430522

Вопрос

Я создал пользовательский интерфейс Converter в JSF 1.2 для преобразования Date Объекты.Даты имеют очень специфический формат.Я реализовал свой конвертер, используя ядро Java SimpleDateFormat класс для выполнения преобразования, используя строку форматирования, показанную в моих комментариях к коду ниже.Все это работает нормально.

Мой вопрос касается потокобезопасности.Тот Самый SimpleDateFormat В документах API указано, что он не является потокобезопасным.По этой причине я создал отдельный экземпляр объекта формата даты для каждого экземпляра моего объекта конвертера.Однако я не уверен, что этого достаточно.Мой DateFormat объект хранится как член DTGDateConverter.

ВОПРОС:Будут ли два потока одновременно обращаться к одному и тому же экземпляру объекта Converter в JSF?

Если ответ положительный, то мой Конвертер, вероятно, находится под угрозой.

/**
 * <p>JSF Converter used to convert from java.util.Date to a string.
 * The SimpleDateFormat format used is: ddHHmm'Z'MMMyy.</p>
 * 
 * <p>Example: October 31st 2010 at 23:59 formats to 312359ZOCT10</p>
 * 
 * @author JTOUGH
 */
public class DTGDateConverter implements Converter {

    private static final Logger logger = 
        LoggerFactory.getLogger(DTGDateConverter.class);

    private static final String EMPTY_STRING = "";

    private static final DateFormat DTG_DATE_FORMAT = 
        MyFormatterUtilities.createDTGInstance();

    // The 'format' family of core Java classes are NOT thread-safe.
    // Each instance of this class needs its own DateFormat object or
    // runs the risk of two request threads accessing it at the same time.
    private final DateFormat df = (DateFormat)DTG_DATE_FORMAT.clone();

    @Override
    public Object getAsObject(
            FacesContext context, 
            UIComponent component, 
            String stringValue)
            throws ConverterException {
        Date date = null;
        // Prevent ParseException when an empty form field is submitted
        // for conversion
        if (stringValue == null || stringValue.equals(EMPTY_STRING)) {
            date = null;
        } else {
            try {
                date = df.parse(stringValue);
            } catch (ParseException e) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Unable to convert string to Date object", e);
                }
                date = null;
            }
        }
        return date;
    }

    @Override
    public String getAsString(
            FacesContext context, 
            UIComponent component, 
            Object objectValue)
            throws ConverterException {
        if (objectValue == null) {
            return null;
        } else if (!(objectValue instanceof Date)) {
            throw new IllegalArgumentException(
                "objectValue is not a Date object");
        } else {
            // Use 'toUpperCase()' to fix mixed case string returned
            // from 'MMM' portion of date format
            return df.format(objectValue).toUpperCase();
        }
    }

}
Это было полезно?

Решение

Будут ли два потока одновременно обращаться к одному и тому же экземпляру объекта Converter в JSF?

Зависит от того, как вы используете конвертер.Если вы используете

<h:inputWhatever>
    <f:converter converterId="converterId" />
</h:inputWhatever>

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

Если вы, однако, используете

<h:inputWhatever converter="#{applicationBean.converter}" />

тогда один и тот же экземпляр будет общим для всех представлений всего приложения, которое, таким образом, не является потокобезопасным.

Однако вы клонируете статический DataFormat создавайте экземпляр каждый раз, когда вы создаете конвертер.Эта часть уже не является потокобезопасной.Вы можете рисковать тем, что клонируете экземпляр, в то время как его внутреннее состояние было изменено, потому что он использовался где-то в другом месте.Кроме того, клонирование существующего экземпляра не обязательно обходится дешевле, чем создание нового экземпляра.

Я бы рекомендовал просто объявить его threadlocal (т. е.внутри блока методов), независимо от того, как вы используете конвертер.Если дороговизна создания DateFormat каждый раз это вызывает серьезную озабоченность (вы описывали это в профиле?), затем подумайте о замене его на ДжодАтим.

Другие советы

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

Да, здесь это не потокобезопасно.

Поместите его локально в метод и создайте экземпляр для каждого потока

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top