Oui, c'est sûr et recommandé.
La seule mise en garde de la page que vous avez mentionnée est que vous ne pouvez pas modifier la configuration du mappeur une fois qu'il est partagé; mais vous ne changez pas la configuration, donc ça va. Si vous aviez besoin de changer la configuration, vous le feriez à partir du bloc statique et ce serait bien aussi.
EDIT : (2013/10)
Avec 2.0 et supérieur, ce qui précède peut être augmenté en notant qu'il existe un meilleur moyen: l'utilisation ObjectWriter
et les ObjectReader
objets, qui peuvent être construits par ObjectMapper
. Ils sont entièrement immuables, thread-safe, ce qui signifie qu'il n'est même pas théoriquement possible de provoquer des problèmes de sécurité des threads (qui peuvent survenir ObjectMapper
si le code tente de reconfigurer l'instance).
ObjectMapper
thread-safeObjectMapper#setDateFormat()
est toujours appelé. Il est connu que ceSimpleDateFormat
n'est pas sûr pour les threads , doncObjectMapper
il ne le sera pas sauf s'il clone par exempleSerializationConfig
avant chaquewriteValue()
(je doute). Pourriez-vous démystifier ma peur?DateFormat
est en effet cloné sous le capot. Bon soupçon là-bas, mais vous êtes couvert. :)ObjectMapper
du tout?! Les méthodes sont nomméeswriter()
etreader()
(et certainesreaderFor()
,writerFor()
).mapper.with()
appel (car "avec" dans Jackson implique la construction d'une nouvelle instance et une exécution thread-safe). Mais en ce qui concerne les changements de configuration: aucune vérification n'est effectuée, donc l'accès à la configurationObjectMapper
doit être gardé. Quant à "copy ()": oui, cela crée une nouvelle copie qui peut être entièrement (re) configurée, selon les mêmes règles: configurez-la entièrement en premier, puis utilisez, et c'est très bien. Il y a un coût non trivial associé (car la copie ne peut utiliser aucun des gestionnaires mis en cache), mais c'est le moyen sûr, oui.Bien que ObjectMapper soit sûr pour les threads, je déconseille fortement de le déclarer comme variable statique, en particulier dans les applications multithread. Pas même parce que c'est une mauvaise pratique, mais parce que vous courez un gros risque de blocage. Je le raconte de ma propre expérience. J'ai créé une application avec 4 threads identiques qui récupéraient et traitaient les données JSON des services Web. Mon application bloquait fréquemment la commande suivante, selon le vidage de thread:
En plus de cela, les performances n'étaient pas bonnes. Lorsque j'ai remplacé la variable statique par la variable basée sur l'instance, le blocage a disparu et les performances ont quadruplé. Soit 2,4 millions de documents JSON ont été traités en 40 minutes 56 secondes, au lieu de 2,5 heures auparavant.
la source
ObjectMapper
instance pour chaque instance de classe peut empêcher les verrous mais peut être très lourd sur GC plus tard (imaginez une instance ObjectMapper pour chaque instance de la classe que vous créez). Une approche intermédiaire peut être, au lieu de conserver une seuleObjectMapper
instance statique (publique) dans l'application, vous pouvez déclarer une instance statique (privée) deObjectMapper
dans chaque classe . Cela réduira un verrouillage global (en répartissant la charge par classe) et ne créera pas non plus de nouvel objet, donc la lumière sur GC aussi.ObjectPool
est la meilleure façon de procéder - donnant ainsi le meilleurGC
et lesLock
performances. Vous pouvez vous référer au lien suivant pour l'ObjectPool
implémentation d' apache-common . commons.apache.org/proper/commons-pool/api-1.6/org/apache/...ObjectMapper
quelque part, mais seulement obtenirObjectReader
/ObjectWriter
instances (via des méthodes d'assistance), conserver les références à celles d'autres endroits (ou appeler dynamiquement). Ces objets de lecture / écriture sont non seulement une reconfiguration wrt entièrement thread-safe, mais aussi très légers (instances de mappeur wrt). Ainsi, conserver des milliers de références n'ajoute pas beaucoup d'utilisation de la mémoire.Bien qu'il soit sûr de déclarer un ObjectMapper statique en termes de sécurité des threads, vous devez savoir que la construction de variables Object statiques en Java est considérée comme une mauvaise pratique. Pour plus de détails, voir Pourquoi les variables statiques sont-elles considérées comme mauvaises? (et si vous le souhaitez, ma réponse )
En bref, la statique doit être évitée car elle rend difficile la rédaction de tests unitaires concis. Par exemple, avec un ObjectMapper final statique, vous ne pouvez pas échanger la sérialisation JSON contre du code factice ou un no-op.
De plus, une finale statique vous empêche de reconfigurer ObjectMapper lors de l'exécution. Vous n'envisagez peut-être pas une raison à cela maintenant, mais si vous vous enfermez dans un modèle final statique, rien de moins que de détruire le chargeur de classe vous permettra de le réinitialiser.
Dans le cas d'ObjectMapper, c'est bien, mais en général c'est une mauvaise pratique et il n'y a aucun avantage à utiliser un modèle singleton ou une inversion de contrôle pour gérer vos objets à longue durée de vie.
la source
readerFor
etwriterFor
créeObjectReader
etObjectWriter
installe à la demande. Je dirais donc de mettre le mappeur avec la configuration initiale quelque part statique, puis d'obtenir des lecteurs / écrivains avec une configuration par cas selon vos besoins?Une astuce que j'ai apprise de ce PR si vous ne voulez pas la définir comme une variable finale statique mais que vous voulez économiser un peu de surcharge et garantir la sécurité des threads.
crédit à l'auteur.
la source
ObjectMapper
sera attaché au thread qui peut faire partie d'un pool.com.fasterxml.jackson.databind.type.TypeFactory._hashMapSuperInterfaceChain (HierarchicType)
La méthode _hashMapSuperInterfaceChain dans la classe com.fasterxml.jackson.databind.type.TypeFactory est synchronisée. Je vois la contention sur le même à des charges élevées.
Peut être une autre raison d'éviter un ObjectMapper statique
la source
TypeReference
c'est une chose un peu chère à utiliser: si possible, le résoudreJavaType
éviterait pas mal de traitement (lesTypeReference
s ne peuvent pas - malheureusement - être mis en cache pour des raisons que je ne vais pas approfondir ici), car ils sont "entièrement résolus" (super-type, typage générique, etc.).