杰克逊图书馆ObjectMapper
班seems to be thread safe。
这是否意味着我应该将ObjectMapper
声明为像这样的静态字段
class Me {
private static final ObjectMapper mapper = new ObjectMapper();
}
而不是像这样的实例级字段?
class Me {
private final ObjectMapper mapper = new ObjectMapper();
}
答案 0 :(得分:458)
是的,这是安全的并且值得推荐。
您引用的页面中唯一的警告是,一旦共享,您就无法修改映射器的配置;但你没有改变配置,所以没关系。如果您确实需要更改配置,那么您可以从静态块执行此操作,它也可以。
编辑 :( 2013/10)
使用2.0及更高版本,可以通过注意更好的方法来增强上述内容:使用ObjectWriter
和ObjectReader
个对象,这些对象可以由ObjectMapper
构建。
它们是完全不可变的,线程安全的,这意味着理论上甚至不可能导致线程安全问题(如果代码尝试重新配置实例,则可能会ObjectMapper
发生)。
答案 1 :(得分:34)
虽然ObjectMapper是线程安全的,但我强烈建议不要将它声明为静态变量,尤其是在多线程应用程序中。 甚至不是因为这是一种不好的做法,而是因为你正面临着陷入僵局的沉重风险。我是根据自己的经验告诉你的。我创建了一个具有4个相同线程的应用程序,这些线程从Web服务获取和处理JSON数据。 根据线程转储,我的应用程序经常停在以下命令上:
Map aPage = mapper.readValue(reader, Map.class);
除此之外,表现并不好。 当我用基于实例的变量替换静态变量时,停顿消失了,性能翻了两番。即在40分57秒内处理了2.4百万个JSON文档,而不是之前的2.5小时。
答案 2 :(得分:2)
虽然在线程安全性方面声明静态ObjectMapper是安全的,但您应该知道在Java中构造静态Object变量被认为是不好的做法。有关详细信息,请参阅Why are static variables considered evil?(如果您愿意,请my answer)
简而言之,应该避免静态,因为难以编写简洁的单元测试。例如,使用静态的最终ObjectMapper,您无法替换虚拟代码或无操作的JSON序列化。
此外,静态final会阻止您在运行时重新配置ObjectMapper。你现在可能没有想到这样的理由,但是如果你把自己锁定在一个静态的最终模式中,那么拆除类加载器就会让你重新初始化它。
在ObjectMapper的情况下它很好,但一般来说这是不好的做法,并且没有使用单例模式或控制反转来管理长期存在的对象的优势。
答案 3 :(得分:0)
如果您不想将其定义为静态最终变量,但又想节省一些开销并确保线程安全,则可以从PR中学到一个技巧。
private static final ThreadLocal<ObjectMapper> om = new ThreadLocal<ObjectMapper>() {
@Override
protected ObjectMapper initialValue() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
return objectMapper;
}
};
public static ObjectMapper getObjectMapper() {
return om.get();
}
致谢作者
答案 4 :(得分:-1)
com.fasterxml.jackson.databind.type.TypeFactory._hashMapSuperInterfaceChain(HierarchicType)
com.fasterxml.jackson.databind.type.TypeFactory._findSuperInterfaceChain(Type, Class)
com.fasterxml.jackson.databind.type.TypeFactory._findSuperTypeChain(Class, Class)
com.fasterxml.jackson.databind.type.TypeFactory.findTypeParameters(Class, Class, TypeBindings)
com.fasterxml.jackson.databind.type.TypeFactory.findTypeParameters(JavaType, Class)
com.fasterxml.jackson.databind.type.TypeFactory._fromParamType(ParameterizedType, TypeBindings)
com.fasterxml.jackson.databind.type.TypeFactory._constructType(Type, TypeBindings)
com.fasterxml.jackson.databind.type.TypeFactory.constructType(TypeReference)
com.fasterxml.jackson.databind.ObjectMapper.convertValue(Object, TypeReference)
类 com.fasterxml.jackson.databind.type.TypeFactory 中的方法_hashMapSuperInterfaceChain已同步。 我在高负荷时看到同样的争论。
可能是避免静态ObjectMapper的另一个原因