【问题标题】:Sharing a class instance between all users with Tomcat使用 Tomcat 在所有用户之间共享一个类实例
【发布时间】:2011-04-14 19:48:18
【问题描述】:

我有一门课,叫counter。它看起来像这样:

public class Counter {
  private int count;

  public Counter() {
    count = 1;
  }

  public int getCount(){
    return count;
  }

  public void incrementCount(){
    count++;
  }

我想在一个 tomcat 应用程序的每个用户之间共享一个这样的实例。 因此,用户 1 和用户 2 都会将 getCount() 视为相同的值。 假设我无法存储和读取数据库是有技术原因的。

有什么建议吗?

谢谢。

【问题讨论】:

    标签: java servlets


    【解决方案1】:

    Just create one 并在服务器启动时存储在应用范围内。

    @WebListener
    public class Config implements ServletContextListener {
    
        @Override
        public void contextInitialized(ServletContextEvent event) {
            event.getServletContext().setAttribute("counter", new Counter());
        }
    
        // ...
    }
    

    这样它在每个 servlet 中都可用,如下所示:

    Counter counter = (Counter) getServletContext().getAttribute("counter");
    // ...
    

    并且在每个 JSP 中如下:

    <p>The count is ${counter.count}</p>
    

    另见:


    与具体问题无关,您的计数器不是线程安全的。我建议使用AtomicInteger 而不是int

    public class Counter {
      private AtomicInteger count = new AtomicInteger();
    
      public Counter() {
        count.incrementAndGet();
      }
    
      public int getCount(){
        return count.get();
      }
    
      public void incrementCount(){
        count.incrementAndGet();
      }
    }
    

    【讨论】:

    • 当然。你不想要一个单身人士。
    • 我只是把它和其他类一起放入包中吗?
    • 听众?是的,它确实需要像您想在 webapp 中使用的所有其他类一样放置在类路径中。然而,我假设您使用的是支持新的 Servlet 3.0 注释的 Tomcat 7。否则,您必须摆脱@WebListener 并在web.xml 中通过&lt;listener&gt; 自己声明侦听器。另请参阅this answer 以获取另一个示例。
    【解决方案2】:

    您可以使用Singleton 模式。

    试试这个:

    public class Counter {
    private int count;
    private static Counter instance = null;
    private static Object lockObj = new Object();
    
    
    
    private Counter() {
    count = 1;
    }
    
    public static Counter Instance(){
     synchronized(lockObj){
         if(instance == null){
            instance = new Counter();
         }
     }
    
     return instance;
    }
    
    public int getCount(){
    return count;
    }
    
    public void incrementCount(){
    count++;
    }
    }
    

    您可以在代码中的某处使用:Counter.Instance().getCount()

    【讨论】:

    • 谢谢。这会让我也增加它吗?
    • 是的,你需要调用 Counter.Instance().incrementCount()
    • 当然你需要注意跨线程的同步
    【解决方案3】:

    一个在 Java 中工作并具有适当锁定的单例:

    public class Counter {
      private AtomicInteger counter = new AtomicInteger(0);
    
      private static class Initilizer {
        private static Counter instance = new Counter();
      }
    
      private Counter() {}
    
      public Counter instance() { return Initilizer.instance; }
    
      public int getCount() { return counter.get() }
      public void increment() { counter.incrementAndGet(); }
    
    }
    

    获取计数:Counter.instance().getCount()
    增量:Counter.instance().increment()

    2个答案的区别在于同步和单例初始化,这是为java优化的

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-09-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多