Question de synchronisation d'applications Web Java
-
03-07-2019 - |
Question
Supposons que j'ai dans mon application Web un cours appelé classe "Foo". Il possède une méthode initialise () appelée lorsque le bean est créé à l'aide de Spring. La méthode initialise () tente ensuite de charger un service externe et de l’affecter à un champ. Si le service n'a pas pu être contacté, le champ sera défini sur null.
private Service service;
public void initialise() {
// load external service
// set field to the loaded service if contacted
// set to field to null if service could not be contacted
}
Lorsque quelqu'un appelle la méthode get () sur la classe "Foo". le service sera appelé s'il a été démarré dans la méthode initialise (). Si le champ du service est null, je souhaite essayer de charger le service externe.
public String get() {
if (service == null) {
// try and load the service again
}
// perform operation on the service is service is not null
}
Puis-je avoir des problèmes de synchronisation si je fais quelque chose comme ça?
La solution
toolkit est correcte. Pour résoudre le problème, déclarez simplement que la méthode initialise () de votre Foo doit être synchronisée. Vous pouvez refactorer Foo comme:
private Service service;
public synchronized void initialise() {
if (service == null) {
// load external service
// set field to the loaded service if contacted
}
}
public String get() {
if (service == null) {
initialise(); // try and load the service again
}
// perform operation on the service is service is not null
}
Autres conseils
Oui, vous aurez un problème de synchronisation.
Supposons que vous ayez une seule servlet:
public class FooServlet extends HttpServlet {
private MyBean myBean;
public void init() {
myBean = (MyBean) WebApplicationContextUtils.
getRequiredWebApplicationContext(getServletContext()).getBean("myBean");
}
public void doGet(HttpRequest request, HttpResponse response) {
String string = myBean.get();
....
}
}
class MyBean {
public String get() {
if (service == null) {
// try and load the service again
}
// perform operation on the service is service is not null
}
}
Et la définition de votre haricot ressemble à:
<bean id="myBean" class="com.foo.MyBean" init-method="initialise" />
Le problème est que votre instance de servlet est utilisée par plusieurs threads de demande. Par conséquent, le bloc de code protégé par service == null peut être entré par plusieurs threads.
La meilleure solution (éviter le double verrouillage, etc.) est la suivante:
class MyBean {
public synchronized String get() {
if (service == null) {
// try and load the service again
}
// perform operation on the service is service is not null
}
}
J'espère que cela a du sens. Laisse un commentaire sinon.