简体   繁体   English

ThreadLocal Singleton

[英]ThreadLocal Singleton

I'm running a RESTful java backend on GlassFish. 我在GlassFish上运行RESTful java后端。 Attached to that is an HTML5 / JS frontend which I can put in a webapp project (and then include the backend as a dependency), or run on an IIS webserver on a different location. 附加一个HTML5 / JS前端,我可以将其放入webapp项目(然后将后端包含为依赖项),或者在不同位置的IIS Web服务器上运行。 CORS is not an issue. CORS不是问题。 Whatever solves this following problem: 无论如何解决以下问题:

Situation: 情况:

  1. User1 logs on and database path is set to 'db/user1/' User1登录,数据库路径设置为'db / user1 /'
  2. User1 inserts 'Value 1' into the database User1将“值1”插入数据库
  3. User2 logs on and database path is set to 'db/user2/' User2登录,数据库路径设置为'db / user2 /'
  4. User1 tries to delete 'Value 1' from database User1尝试从数据库中删除“值1”

User1 would not be able to delete Value 1 from db/user1, since the databasepath has been changed to db/user2 and there is no Value 1 in that database. User1将无法从db / user1中删除值1,因为数据库路径已更改为db / user2且该数据库中没有值1。

public class DataAccess{
    private static DataAccess dataaccess;
    private String databasepath;

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

How can I modify the getInstance() method so that it acts as a singleton, but only inside the thread of that user? 如何修改getInstance()方法以使其充当单例,但仅在该用户的线程内? I saw something called threadlocal but didn't fully understand it, is that perhaps a solution? 我看到了一些名为threadlocal的东西,但没有完全理解它,这可能是一个解决方案吗?

Any help is most certainly appreciated. 任何帮助肯定是值得赞赏的。

You could use the ThreadLocal class in a factory pattern: 可以在工厂模式中使用ThreadLocal类:

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();
    }
}

This will, however, cause a memory leak. 但是,这会导致内存泄漏。 So you need to use a Servlet Filter to set the value at the start of a request and then delete it at the end, some like: 因此,您需要使用Servlet过滤器在请求开始时设置值,然后在最后删除它,例如:

   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();
      }
   }

Once you have a class that implements Filter you add it to your web.xml thus: 一旦有了实现Filterclass ,就可以将它添加到web.xml

<!--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>

This page gives an example of a filter and its mappings. 页面提供了过滤器及其映射的示例。
And your DataAccess would look like: 您的DataAccess看起来像:

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();
    }
}

Be extremely careful with ThreadLocal as it is probably the number one cause of memory leaks in Java. ThreadLocal非常小心,因为它可能是Java中内存泄漏的首要原因。 With web servers that have thread pools you can get even more serious bugs if you don't clean them out properly. 对于具有线程池的Web服务器,如果不正确清除它们,则可能会遇到更严重的错误。

Looks that ThreadLocal should help you with your use-case: 看起来ThreadLocal应该帮助您处理用例:

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

This class provides thread-local variables. 该类提供线程局部变量。 These variables differ from their normal counterparts in that each thread that accesses one (via its get or set method) has its own, independently initialized copy of the variable. 这些变量与它们的正常对应物的不同之处在于,访问一个变量的每个线程(通过其get或set方法)都有自己独立初始化的变量副本。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM