【问题标题】:Is making a GWT asynccallback in a constructor safe?在构造函数中进行 GWT 异步回调安全吗?
【发布时间】:2013-04-08 07:46:51
【问题描述】:

假设构造函数在代码的客户端部分(被翻译成 javascript 的部分)中运行。 回调方法 onSuccess 确实修改了类的实例变量。 回调被实现为匿名类,因此可以使用 OuterClass.this 访问外部类的实例。

通常在纯 Java 中我们不应该这样做,因为这样做,'this' 引用可以在对象构造完成之前逃逸。

但它也适用于将 Java 代码转换为 Javascript 的情况吗?我假设 javascript 代码是由网络浏览器中的单个线程执行的,所以这应该不是问题(单线程 => 没有可见性问题)?

【问题讨论】:

    标签: multithreading gwt thread-safety gwt-rpc


    【解决方案1】:

    一方面,您是对的 - 问题不能由单独的线程触发,因为 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
    

    (尽管 'some' 是最终的)。这在 GWT(已编译/未编译)和纯 Java 程序中都会发生。

    【讨论】:

      【解决方案2】:

      AsyncCallback 本身只是一个类。在生产模式下发送 RPC 请求时,保证结果会通过 XmlHttpRequest 异步传入;在已编译的 javascript 中,在构造完成之前泄漏引用是 100% 不可能的,因为回调将在单独的 javascript 执行堆栈中被调用。

      然而,在 gwt-dev 模式下,应该是异步的事情并不总是这样。就个人而言,我放弃了 gwt-dev 而不是 super-dev-mode,并且仅在我确实需要 java 调试器时才使用 gwt-dev,所以我无法确定它是否会不受构造问题的影响(测试它并找出来!)。

      如果您没有在构造函数中发送任何请求,您将是 100% 安全的。如果您随后以不安全的方式访问 OuterClass.this,则仅创建异步回调只会导致问题,而不管涉及的类如何。

      【讨论】:

        猜你喜欢
        • 2015-07-09
        • 2020-07-28
        • 2018-09-16
        • 2015-05-08
        • 2019-12-11
        • 2011-12-30
        相关资源
        最近更新 更多