如何防止vaadin应用程序实例互相干扰?

时间:2011-11-15 10:39:33

标签: singleton vaadin thread-local

我有一个Vaadin应用程序,当我同时运行两个应用程序实例时,我会遇到一些奇怪的行为(一个在FF,另一个在IE中)。我已经删除了大多数静态对象(这些导致应用程序在与另一个打开的应用程序并行使用时完全重新加载),现在我可以正常地与UI进行交互,而无需完全重置。但是,我现在注意到我在两个接口中只获得了一个用户的数据。我假设这是由我用来管理一些数据缓存和SOAP连接的单例对象引起的。我想知道它是单独的模式本身导致奇怪的输出还是只是我保留的静态实例对象?

我尝试将ThreadLocal与我的单例一起使用,但是当我尝试在我的单例函数中使用它们时,我的所有变量都是null。目前我的单身人士包含了这个,这可能非常糟糕,因为它不起作用。

private static ThreadLocal<SoapClient> instance = new ThreadLocal<SoapClient>();

public static synchronized SoapClient getInstance(){
    if (instance.get() == null) {
        instance.set(new SoapClient());
    }
    return instance.get();
}

我选择了一个单例对象,所以我总是可以访问我的应用程序实例中的缓存数据和我的用户的soap连接,而我能想到的另一种方法就是在某个地方有一个静态对象,但是静态关键字似乎首先是我所有问题的原因。有什么方法可以解决这个问题还是有其他原因导致它?

1 个答案:

答案 0 :(得分:5)

本地实例化线程的更好方法是

ThreadLocal<SoapClient> instance = new ThreadLocal<String>() {
  @Override
  protected String initialValue() {
    return new SoapClient();    
  }
}

但是,您的问题是Web应用服务器“池”并重新使用线程。在Vaadin术语中,并非每个应用程序请求都处理相同的线程 - 即Thread1可以处理App实例1和App实例2的请求。如果您的SoapClient缓存适用于App实例1的信息,则App 2的UI可能最终使用App 1的SoapClient。

假设(根据您的描述)“特定应用”信息缓存在SoapClient中,我建议您

  • 在您的Application对象上创建和存储SoapClient作为普通字段(不是静态字段,而不是threadlocal)

  • 如果您需要访问该应用程序(以获取SoapClient),并且从您所处的位置来看很棘手,请使用ThreadLocal access pattern。请参阅链接上的第二个示例。请注意,ThreadLocal在HttpRequest的开头设置,并在结尾处“取消设置”,确保同一线程上的任何后续请求都不会获得相同的应用程序实例。