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?

Était-ce utile?

La solution

La réponse de

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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top