创建XMLGregorianCalendar时DataTypeFactory的使用会严重影响性能

Ram*_*man 13 java performance jaxb

给定时间(以毫秒为单位),我们可以使用以下代码段创建XMLGregorianCalendar.

GregorianCalendar greCal = new GregorianCalendar();
greCal.setTimeInMillis(timeInMilliseconds);
XMLGregorianCalendar xmlCal = DatatypeFactory.newInstance().newXMLGregorianCalendar(greCal));
Run Code Online (Sandbox Code Playgroud)

但问题是,它严重影响了性能.

http://www.java.net/node/666491

有一个与SUN提交的错误,但他们没有列出任何变通方法. http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6466177

试图寻找其他替代方案,但徒劳无功.你们中的任何一个人都可以选择其他人吗?

谢谢

拉曼

Viv*_*ivo 13

昂贵的部分是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);
    // ...
}
Run Code Online (Sandbox Code Playgroud)

  • 理论上是的,但目前的实现是线程安全的,说实话,有人必须努力使其成为无线程安全的.(如果只有同一个人写了SimpleDateFormat,那么这个世界将是一个更幸福的地方). (8认同)

Nik*_*ita 9

由于@VivaceVivo提到DataFactory.newInstance()是昂贵的并且impl不保证是线程安全的,考虑使用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);
    }
}
Run Code Online (Sandbox Code Playgroud)

..只要你不关心线程是否保留额外的对象,或者在需要时有办法清除ThreadLocalMap