La classe ObjectMapper
de la bibliothèque Jackson semble être thread-safe .
Est-ce que cela signifie que je devrais déclarer ma ObjectMapper
comme un champ statique comme celui-ci?
class Me {
private static final ObjectMapper mapper = new ObjectMapper();
}
au lieu d'un champ de niveau instance comme celui-ci?
class Me {
private final ObjectMapper mapper = new ObjectMapper();
}
Oui, c'est sûr et recommandé.
La seule réserve de la page que vous avez évoquée est que vous ne pouvez pas modifier la configuration du mappeur une fois qu'il est partagé; mais vous ne modifiez pas la configuration, donc ça va. Si vous deviez modifier la configuration, vous le feriez à partir du bloc statique et tout irait bien.
EDIT: (2013/10)
Avec les versions 2.0 et supérieures, il est possible d’augmenter les options ci-dessus en notant qu’il existe une méthode encore meilleure: utilisez des objets ObjectWriter
et ObjectReader
, qui peuvent être construits par ObjectMapper
. Ils sont totalement immuables, thread-safe, ce qui signifie qu’ils ne sont pas théoriquement possible de causer des problèmes de sécurité des threads (ce qui peut se produire avec ObjectMapper
si le code tente de reconfigurer l'instance).
Bien qu'ObjectMapper soit thread-safe, je déconseillerais fortement de la déclarer comme une variable statique, en particulier dans les applications multithreads . Pas même parce que c'est une mauvaise pratique, mais parce que vous courez un risque important de blocage. Je le dis de ma propre expérience. J'ai créé une application avec 4 threads identiques qui obtenaient et traitaient des données JSON à partir de services Web . Mon application bloquait fréquemment la commande suivante, en fonction du vidage de thread:
Map aPage = mapper.readValue(reader, Map.class);
De plus, les performances n'étaient pas bonnes… .. Lorsque j'ai remplacé la variable statique par la variable basée sur l'instance, le décrochage a disparu et les performances ont été quadruplées. C'est à dire. 2,4 millions de documents JSON ont été traités en 40 minutes et 56 secondes, au lieu de 2,5 heures auparavant.
Bien qu'il soit prudent de déclarer un ObjectMapper statique en termes de sécurité des threads, vous devez savoir que la construction de variables d'objet 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 voulez, ma réponse )
En bref, la statique doit être évitée car il est difficile d’écrire des 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 non-op.
De plus, une finale statique vous empêche de reconfigurer ObjectMapper au moment de l'exécution. Vous n'envisagez peut-être pas une raison pour cela maintenant, mais si vous vous enfermez dans un modèle final statique, rien de moins que de démolir le chargeur de classes 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’ya aucun avantage à utiliser un modèle singleton ou une inversion de contrôle pour gérer vos objets de longue durée.
Un truc que j’ai appris de ceci PR si vous ne voulez pas le définir comme une variable finale statique mais voulez économiser un peu de temps système et garantir la sécurité des threads.
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();
}
crédit à l'auteur.