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

Singleton 如何防止vaadin应用程序实例相互干扰?,singleton,vaadin,thread-local,Singleton,Vaadin,Thread Local,我有一个Vaadin应用程序,当同时运行两个应用程序实例(一个在FF中,另一个在IE中)时,会出现一些奇怪的行为。我已经删除了大多数静态对象(当与另一个打开的应用程序并行使用时,这些静态对象会导致应用程序完全重新加载),现在我可以在不完全重置的情况下与UI正常交互。然而,我现在注意到,我在两个界面中只获得了一个用户的数据。我假设这是由我用来管理一些数据缓存和SOAP连接的单例对象引起的。我想知道是单例模式本身导致了奇怪的输出,还是我保留的只是静态实例对象 我已经尝试在我的singleton函数中

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

我已经尝试在我的singleton函数中使用ThreadLocal,但是当我尝试在我的singleton函数中使用它们时,我的所有变量总是空的。目前我的单例包含这个,这可能是非常非常错误的,因为它不工作

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

public static synchronized SoapClient getInstance(){
    if (instance.get() == null) {
        instance.set(new SoapClient());
    }
    return instance.get();
}
private static ThreadLocal instance=new ThreadLocal();
公共静态同步SoapClient getInstance(){
if(instance.get()==null){
set(新的SoapClient());
}
返回instance.get();
}

我选择了一个单例对象,这样我在应用程序实例中的任何地方都可以访问缓存的数据和用户的soap连接,我能想到的唯一其他方法是在某个地方有一个静态对象,但static关键字似乎是我所有问题的根源。有没有办法解决这个问题,或者是其他原因造成的

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

ThreadLocal<SoapClient> instance = new ThreadLocal<String>() {
  @Override
  protected String initialValue() {
    return new SoapClient();    
  }
}
ThreadLocal实例=新ThreadLocal(){
@凌驾
受保护的字符串initialValue(){
返回新的SoapClient();
}
}
然而,这里的问题是web应用服务器“池”和重用线程。在Vaadin术语中,并非每个应用程序的请求都由同一个线程处理,即Thread1可以同时处理应用程序实例1和应用程序实例2的请求。如果您的SoapClient缓存了适用于应用程序实例1的信息,则应用程序2的UI最终可能会使用应用程序1的SoapClient

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

  • 在应用程序对象上创建并存储SoapClient作为普通字段(非静态,非threadlocal)

  • 如果您需要访问应用程序(以便获得SoapClient),并且从您所在的位置很难访问,请使用。请参见链接上的第二个示例。请注意,ThreadLocal设置在HttpRequest的开头,并在末尾设置为“unset”,以确保同一线程上的任何后续请求不会获得相同的应用程序实例


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

      ThreadLocal<SoapClient> instance = new ThreadLocal<String>() {
        @Override
        protected String initialValue() {
          return new SoapClient();    
        }
      }
      
      ThreadLocal实例=新ThreadLocal(){
      @凌驾
      受保护的字符串initialValue(){
      返回新的SoapClient();
      }
      }
      
      然而,这里的问题是web应用服务器“池”和重用线程。在Vaadin术语中,并非每个应用程序的请求都由同一个线程处理,即Thread1可以同时处理应用程序实例1和应用程序实例2的请求。如果您的SoapClient缓存了适用于应用程序实例1的信息,则应用程序2的UI最终可能会使用应用程序1的SoapClient

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

      • 在应用程序对象上创建并存储SoapClient作为普通字段(非静态,非threadlocal)

      • 如果您需要访问应用程序(以便获得SoapClient),并且从您所在的位置很难访问,请使用。请参见链接上的第二个示例。请注意,ThreadLocal设置在HttpRequest的开头,并在末尾设置为“unset”,以确保同一线程上的任何后续请求不会获得相同的应用程序实例