Вопрос синхронизации веб-приложений Java - PullRequest
1 голос
/ 23 октября 2008

Допустим, у меня есть класс в моем веб-приложении, называемый классом "Foo". У него есть метод initialise (), который вызывается при создании компонента с помощью Spring. Затем метод initialise () пытается загрузить внешнюю службу и назначить ее полю. Если со службой невозможно связаться, поле будет установлено в ноль.

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
}

Когда кто-то вызывает метод get () для класса "Foo", служба вызывается, если она была запущена в методе initialise (). Если поле для службы пустое, я хочу попробовать загрузить внешнюю службу.

public String get() {
    if (service == null) {
        // try and load the service again
    }
    // perform operation on the service is service is not null
}

Возможно ли, что у меня могут возникнуть проблемы с синхронизацией, если я сделаю что-то подобное?

Ответы [ 2 ]

1 голос
/ 23 октября 2008

toolkit ответ правильный. Чтобы решить эту проблему, просто объявите метод initialise () вашего Foo для синхронизации. Вы можете рефакторинг Foo как:

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
}
0 голосов
/ 23 октября 2008

Да, у вас будет проблема с синхронизацией.

Предположим, у вас есть один сервлет:

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
    }
}

И ваше определение бина выглядит так:

<bean id="myBean" class="com.foo.MyBean" init-method="initialise" />

Проблема в том, что ваш экземпляр сервлета используется несколькими потоками запросов. Следовательно, кодовый блок, защищенный service == null, может быть введен несколькими потоками.

Лучшее исправление (избегая двойной проверки блокировки и т. Д.):

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
    }
}

Надеюсь, это имеет смысл. Оставьте комментарий, если нет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...