Использование DataTypeFactory при создании XMLGregorianCalendar сильно ухудшает производительность
Учитывая время в миллисекундах, мы можем создать XMLGregorianCalendar, используя следующий фрагмент.
GregorianCalendar greCal = new GregorianCalendar();
greCal.setTimeInMillis(timeInMilliseconds);
XMLGregorianCalendar xmlCal = DatatypeFactory.newInstance().newXMLGregorianCalendar(greCal));
Но проблема в том, что она плохо справляется с производительностью.
http://www.java.net/node/666491
Есть ошибка, связанная с этим с SUN, но они не указали никаких обходных решений.
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6466177
Пробовал искать другую альтернативу, но напрасно. У любого из вас есть альтернатива сделать то же самое?
Спасибо
комбинационное
Ответы
Ответ 1
Дорогая часть - DatatypeFactory.newInstance(), она отображается справа сверху при профилировании приложения.
В нашем случае мы сохранили DatatypeFactory как статическую переменную, и нам удалось обойти повторную инициализацию. Это должно работать, потому что используемая нами реализация DatatypeFactory должна быть потокобезопасной (как указано в отчете об ошибке). Я согласен, что есть вероятность, что это может измениться в зависимости от используемой реализации. Поэтому я рекомендую дважды проверять.
private static DatatypeFactory datatypeFactory;
static{
try {
datatypeFactory = DatatypeFactory.newInstance();
} catch (DatatypeConfigurationException e) {
throw new RuntimeException("Init Error!", e);
}
}
public void foo(long timeInMilliseconds){
GregorianCalendar greCal = new GregorianCalendar(); greCal.setTimeInMillis(timeInMilliseconds);
XMLGregorianCalendar xmlGregorienCalendar = datatypeFactory.newXMLGregorianCalendar(greCal);
// ...
}
Ответ 2
Так как @VivaceVivo упоминает DataFactory.newInstance() дорого, и им не гарантировано быть потокобезопасным, рассмотрите возможность использования ThreadLocal:
final private static ThreadLocal<DatatypeFactory> datatypeFactoryHolder = new ThreadLocal<DatatypeFactory>()
{
@Override
protected DatatypeFactory initialValue()
{
try
{
return DatatypeFactory.newInstance();
} catch (DatatypeConfigurationException e)
{
throw new IllegalStateException("failed to create " + DatatypeFactory.class.getSimpleName(), e);
}
}
};
public static XMLGregorianCalendar dateToXMLGregorianCalendar(Date date)
{
GregorianCalendar c = new GregorianCalendar();
c.setTime(date);
return datatypeFactoryHolder.get().newXMLGregorianCalendar(c);
}
}
.. до тех пор, пока вам все равно, если потоки сохраняют дополнительный объект или имеют способ очистки ThreadLocalMap при необходимости