Jackson库的ObjectMapper
类seems to be thread safe。
这是否意味着我应该像这样将ObjectMapper
声明为静态字段
class Me {
private static final ObjectMapper mapper = new ObjectMapper();
}
而不是像这样的示例级字段?
class Me {
private final ObjectMapper mapper = new ObjectMapper();
}
6条答案
按热度按时间oo7oh9g91#
是的,这是安全和推荐的。
你提到的页面中唯一的警告是,一旦共享了Map器,你就不能修改它的配置;但是你没有改变配置,所以这很好。如果您确实需要更改配置,您可以从静态块中进行更改,这也很好。
编辑:(2013/10)
在2.0及以上版本中,可以通过注意到有一种更好的方法来增强上述内容:使用
ObjectWriter
和ObjectReader
对象,它们可以由ObjectMapper
构造。它们是完全不可变的,线程安全的,这意味着理论上甚至不可能导致线程安全问题(如果代码试图重新配置示例,ObjectMapper
可能会发生)。hxzsmxv22#
虽然ObjectMapper是线程安全的,但我强烈建议不要将其声明为静态变量,特别是在多线程应用程序中。这并不是因为它是一个糟糕的实践,而是因为您正在冒着死锁的巨大风险。我是根据自己的经验说的。我创建了一个具有4个相同线程的应用程序,这些线程从Web服务中获取和处理JSON数据。根据线程转储,我的应用程序经常在执行以下命令时停止:
除此之外,表现并不好。当我用基于示例的变量替换静态变量时,停顿消失了,性能翻了两番。也就是说,240万个JSON文档在40分钟56秒内被处理,而不是之前的2.5小时。
deikduxw3#
如果你不想把它定义为一个静态的final变量,但想保存一点开销并保证线程安全,我从这个PR中学到了一个技巧。
作者的信用。
zour9fqk4#
尽管从线程安全性的Angular 来看,声明静态ObjectMapper是安全的,但您应该意识到,在Java中构造静态Object变量被认为是不好的做法。有关详细信息,请参阅Why are static variables considered evil?(如果您愿意,请参阅my answer)
简而言之,应该避免静态测试,因为静态测试会使编写简洁的单元测试变得困难。例如,使用静态final ObjectMapper,您不能将JSON序列化换成伪代码或no-op。
此外,静态final防止您在运行时重新配置ObjectMapper。您现在可能无法想象这样做的原因,但是如果您将自己锁定在静态final模式中,那么除了拆除类加载器之外,没有什么可以让您重新初始化它。
在ObjectMapper的情况下,它是好的,但一般来说,这是一个坏的做法,并没有比使用单例模式或控制反转来管理长期对象的优势。
dluptydi5#
类com.fasterxml.Jackson.databind.type.TypeFactory中的方法_hashMapSuperInterfaceChain已同步。我看到在高负载下同样存在争用。
这可能是避免使用静态ObjectMapper的另一个原因
fcy6dtqo6#
这个问题可能很老了,但我是这么做的。
将
ObjectMapper
示例保存在线程安全的单例中: