我正在尝试使用会话使 servlet 线程安全。我已经阅读了不同的技术,例如同步块、AtomicReference 或 ConcurrentHashMap。如果有的话,每种技术的权衡是什么?
3 回答
servlet 的第一个目标是通过无共享状态来实现线程安全。任何共享状态都不会是 servlet 部署到负载平衡集群时的状态。因此,如果您的共享状态不是缓存风格,这意味着它总是可以从持久存储中重建,那么您一开始就不应该拥有它。
但是,除了这些问题之外,如果不提供有关您尝试使用共享状态解决的问题的任何详细信息,您就无法获得一刀切的答案。您提到的所有技术都有优点,这就是为什么在使用 Java 15 年之后它们仍然存在于我们身边的原因。
servlet 不应该有状态,即受其请求处理方法影响的实例或静态变量(此外,它的请求处理方法不应影响任何共享对象的状态)。每个 servlet 容器只有一个 servlet 实例,每个请求都使用一个新的线程来处理,该线程运行适当的 Servlet 方法(更常见的是 doGet() 或 doPost())。
但是,servlet API 提供了以开箱即用的线程安全方式存储与特定用户会话相关的数据所需的所有功能。例如,您可以通过 HttpServletRequest#getSession() 获取会话,并使用其 setAttribute() 方法将对象存储在特定会话中,并使用 getAttribute() 在同一会话的另一个请求中获取它们。
希望这可以帮助。
首先,servlet 应该是无状态的,这有利于应用程序的可扩展性。实际上,基于 Servlet API 的 Session Object 具有很强的可扩展性,您可以编写自己的 HttpSession 实现,使 Session 访问线程安全。恕我直言,您应该提供更多场景的详细信息,因为在您上面提到的那些数据结构中,最后两个似乎与 Session 的线程安全访问无关。