首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ThreadLocal Singleton

ThreadLocal Singleton
EN

Stack Overflow用户
提问于 2013-02-19 13:57:45
回答 2查看 11.1K关注 0票数 8

我正在GlassFish上运行一个GlassFish java后端。附加到它的是一个HTML5 / JS前端,我可以将它放在一个webapp项目中(然后将后端作为一个依赖项),或者在一个不同位置的IIS上运行。CORS不是问题。解决以下问题的方法是:

情况:

  1. User1登录并将数据库路径设置为“db/user1 1/”
  2. User1将‘值1’插入数据库
  3. User2登录并将数据库路径设置为“db/user2 2/”
  4. User1试图从数据库中删除'Value 1‘

User1将无法从db/user1 1中删除值1,因为数据库路径已更改为db/user1 2,并且该数据库中没有值1。

代码语言:javascript
复制
public class DataAccess{
    private static DataAccess dataaccess;
    private String databasepath;

    public static DataAccess getInstance() {
        if (dataaccess == null) {
            dataaccess = new DataAccess();
        }
    }
}

我如何修改getInstance()方法,使其充当单例,但只在该用户的线程中?我看到了一些叫做线程本地的东西,但没有完全理解它,这也许是一个解决方案吗?

任何帮助都是非常感谢的。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-02-19 14:06:11

您可以在工厂模式中使用ThreadLocal类:

代码语言:javascript
复制
public class DataAccess{
    private static ThreadLocal<DataAccess> THREAD_LOCAL = new ThreadLocal() {
     @Override
     protected DataAccess initialValue() {
             return new DataAccess();
     }
    };
    private String databasepath;

    public static DataAccess getInstance() {
      return THREAD_LOCAL.get();
    }
}

然而,这将导致内存泄漏。因此,您需要使用Servlet过滤器在请求开始时设置值,然后在请求结束时删除它,如下所示:

代码语言:javascript
复制
   public void doFilter(ServletRequest request,
      ServletResponse response, FilterChain chain) 
      throws IOException, ServletException {
      DataAccess.set(new DataAccess("SomeValue"));
      try {
        chain.doFilter(request, response);
      } finally {
        DataAcess.remove();
      }
   }

一旦您有了一个实现class过滤器,就可以将它添加到您的web.xml中,这样:

代码语言:javascript
复制
<!--Filter for adding in dataccess objects-->
<filter>
    <filter-name>DataccessFilter</filter-name>
    <filter-class>my.package.DataccessFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>DataccessFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

页面给出了一个过滤器及其映射的示例。

你的DataAccess看起来就像:

代码语言:javascript
复制
public class DataAccess{
    private static ThreadLocal<DataAccess> THREAD_LOCAL = new ThreadLocal();
    private String databasepath;

    public DataAcess(final String databasepath) {
      this.databasepath = databasepath;
    }

    public static DataAccess getInstance() {
      return THREAD_LOCAL.get();
    }
    public static void set(final DataAccess dataAccess) {
      THREAD_LOCAL.set(dataAccess);
    }
    public static void remove() {
      THREAD_LOCAL.remove();
    }
}

非常小心地使用ThreadLocal,因为它可能是造成Java内存泄漏的头号原因。对于有线程池的web服务器,如果不正确地清除它们,您可能会得到更严重的错误。

票数 11
EN

Stack Overflow用户

发布于 2013-02-19 13:59:32

看来ThreadLocal应该可以帮助您完成用例:

http://docs.oracle.com/javase/6/docs/api/java/lang/ThreadLocal.html

这个类提供线程局部变量.这些变量与它们的正常对应变量不同,因为每个访问一个线程(通过其get或set方法)都有它自己的、独立初始化的变量副本。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14959295

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档