2013-04-08 4 views
4

Предполагая, что конструктор запускается в клиентской части кода (тот, который переводится на javascript). Метод обратного вызова onSuccess изменяет переменные экземпляра класса. Обратный вызов реализован как анонимный класс, поэтому к экземпляру внешнего класса можно получить доступ с помощью OuterClass.this.Делает GWT asynccallback в конструкторе безопасным?

Обычно в простой Java мы не должны делать что-то подобное, потому что при этом «эта» ссылка может выйти до завершения построения объекта.

Но это также относится к случаю, когда код Java переведен на Javascript? Я предполагаю, что javascript-код выполняется одним потоком в веб-браузере, поэтому это не должно быть проблемой (single thread => no visibility problems)?

ответ

2

AsyncCallback, сам по себе, является просто классом. Когда вы отправляете запрос RPC в режиме производства, вам гарантируется, что результат будет поступать асинхронно через XmlHttpRequest; в скомпилированном javascript на 100% невозможно пропустить ссылку до завершения строительства, так как обратный вызов будет вызван в отдельном стеке выполнения javascript.

В режиме gwt-dev все, что должно быть асинхронным, не всегда так. Лично я отказался от gwt-dev над супер-dev-mode и использовал gwt-dev, когда мне действительно нужен java-отладчик, поэтому я не могу точно сказать вам, будет ли он защищен от проблем с конструкцией или нет (проверьте его и узнайте!).

Если вы не отправляете никаких запросов в конструкторе, вы будете на 100% безопаснее. Простое создание асинхронного обратного вызова приведет только к проблемам, если вы впоследствии обращаетесь к OuterClass.Это небезопасно, независимо от того, какие классы были задействованы.

3

С одной стороны, вы правы - проблема не может быть вызвана отдельным потоком, потому что JavaScript однопоточный.

События обратного вызова, безусловно, будут обработаны обработчиком событий, который начинается после завершения текущего обработчика событий (того, который строит текущий объект). Поэтому они будут видеть только полностью построенный объект.

С другой стороны, вы, как правило, не нуждаетесь в потоках, чтобы использовать основную проблему. Вот простой пример:

final A a = new A(); 
final B b = new B(a); 
public class A { 

    private B b; 

    public void setB(final B b) { 
    this.b = b; 
    } 

    public void letBSaySomething() { 
    b.saySomething(); 
    } 
} 
public class B { 

    private A a; 
    private final int some; 

    public B(final A a) { 
    this.a = a; 
    a.setB(this); 

    a.letBSaySomething(); 
    some = 55; 
    a.letBSaySomething(); 
    } 

    public void saySomething() { 
    RootPanel.get().add(new Label("Hello " + some)); 
    } 
} 

Это приводит к выходу

Hello 0 
Hello 55 

(хотя 'некоторые' является окончательным). Это происходит как в GWT (скомпилированном/некомпилированном), так и в простых Java-программах.

Смежные вопросы