Est RestTemplate thread-safe?
Est un Printemps RestTemplate
thread-safe? C'est
- Est un
RestTemplate
une Stratégie de l'objet de multiples connexions pouvez partager en toute sécurité. ou - Est un
RestTemplate
un objet de connexion (comme une base de données de connexion), qui ne peuvent pas être partagées lors de l'utilisation, et nécessite la création de nouveau, ou de mise en commun, pour chaque connexion.
- Je réponds à ma propre question, qu'est encouragé.
- Voir aussi stackoverflow.com/questions/21242812/...
- Voir aussi stackoverflow.com/questions/21145558/...
- Voir aussi stackoverflow.com/questions/6747478/...
Vous devez vous connecter pour publier un commentaire.
RestTemplate
est thread-safe (italiques ajoutés):Objets de la
RestTemplate
classe de ne pas modifier leurs informations d'état de processus de HTTP: la classe est une instance de la Stratégie de modèle de conception, plutôt que comme un objet de connexion. Avec aucune information d'état, il n'y a pas de possibilité de fils de corrompre ou de courses, les informations d'état si elles partagent unRestTemplate
objet. C'est pourquoi il est possible pour les threads de partager ces objets.Si vous examinez le code source de
RestTemplate
vous verrez qu'il n'utilise passynchronized
méthodes ouvolatile
champs pour fournir thread-safety après la construction de l'objet. C'est donc pas sûr pour modifier unRestTemplate
objet après la construction. En particulier, il est dangereux d'ajouter un message converter.De lui fournir une liste de message convertisseurs vous devez effectuer l'une des opérations suivantes:
RestTemplate(List<HttpMessageConverter<?>> messageConverters)
constructeur. Comme la liste interne demessageConverters
estfinal
, ce en toute sécurité publie la liste de message convertisseurs.setMessageConverters(List<HttpMessageConverter<?>> messageConverters)
mutateur et puis en toute sécurité-publier la changéRestTemplate
objet. L'aide d'un Ressort de haricots définition qui a une<property name="messageConverters"><list>...
cela, comme le haricot sera en toute sécurité publié par le fil configuration du conteneur dans la plupart des cas pratiques.List.add
sur la référence renvoyée pargetMessageConverters()
et en toute sécurité de publier le changéRestTemplate
objet. Toutefois, la documentation deRestTemplate
n'est pas dit explicitement qu'il renvoie une référence qui peut être utilisé pour modifier la liste de message convertisseurs. L'implémentation actuelle ne, mais peut-être la mise en œuvre pourrait être modifié pour renvoyer unCollections.unmodifiableList
ou une copie de la liste. Il pourrait donc être préférable de ne pas changer de cette façon.Noter que le premier cas est le seul moyen de configurer le message convertisseurs lors de la construction de l'objet, de sorte qu'il est correct de dire que c'est "thread-safe, une fois construite".
La classe fait partie du Framework Spring, dans presque tous les cas pratiques objets de la classe sera mis en place dans le cadre d'un Ressort de Contexte de l'Application, à l'aide de la première (injection de dépendance à l'aide d'un constructeur) ou la deuxième (injection de dépendance à l'aide d'un setter) des méthodes, et donc la garantie d'être en toute sécurité publié à plusieurs threads.
RestTemplate
n'étant pas thread-safe.Il est thread-safe à partir de la bibliothèque de point de vue. Par exemple, le getMessageConverters() est public, ce Qui signifie que si quelqu'un met la main sur la liste et les modifie à l'extérieur de l'objectif de la bibliothèque puis il va provoquer des problèmes (et même de la méthode de définition, si elle est appelée à tout moment après le RestTemplate instanciation et tout en étant utilisé par d'autres threads évidemment, boom!). Ce qui est probablement ce qui est arrivé à Ross (pas assez de réputation pour répondre à la réponse, mais je suis à sauvegarder à la fois le "thread-safe" et pas "thread-safe" arguments)
Bien, bien que je pourrais creuser l'ancien code de contrôle de code source qui a causé ces problèmes.
Je pense qu'il serait juste de dire que même la synchronisation sur la création, il existe des circonstances où un autre thread peut modifier l'intérieur des collections. Donc il vaut mieux être prudent.
En regardant l'ancien code, oui, il était en fait à l'aide d'un message converter. Mais seulement lorsqu'il est synchronisé sur la création.
Après que la seule interaction avec RestTemplate était avec ceci:
C'est aussi la ligne qui finalement lève l'exception.
Il n'y a évidemment pas d'interaction avec le message convertisseur (nous n'avons pas de local de référence).
À la recherche à la stacktrace, et le source code, l'erreur s'est produite à la ligne:
Donc, qu'avons-nous?
Donc en résumé, il y a des circonstances où les choses ne sont pas thread-safe, surtout si vous avez été à jouer avec message convertisseurs directement. Ce cas est étrange, mais j'ai pensé qu'il serait utile de le publier.
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
mais de ne pas publier en toute sécurité, le changement fait àrestTemplate
.restTemplate.getMessageConverters().add(...
n'est pas fait dans un thread de manière sûre.Hate d'être en désaccord avec la accepté la réponse ci-dessus (emphase ajoutée), mais non ce n'est pas Thread-safe. Même après la création. En interne, c'est de jouer avec les ArrayLists, je n'ai pas creusé dans la source. J'ai vu trop de ces:
RestTemplate
. Que l'exception est unConcurrentModificationException
n'indique pas queRestTemplate
n'est pas "thread-safe" une fois construits. Il est compatible avec votre code ayant modifié leRestTemplate
objet, ou de l'une de ses contenusArrayList
objets (tels que la liste de message convertisseurs) après la construction de l'objet.synchonized
mot-clé.