在Java中,如何确保我的Web应用程序是线程安全的?

2022-09-03 17:16:20

如何确保我的java servlets Web应用程序是线程安全的?对于会话变量、类的静态变量或其他任何可能成为线程安全问题的内容,我需要执行哪些操作?


答案 1

事实:在 Web 应用的生命周期中,只有 1 个 servlet 实例。它是在webapp启动时创建的,并在webapp关闭时被摧毁。另请参阅此答案以进行粗略解释。

因此,它已在所有请求(线程)之间共享。如果将请求或会话范围的数据分配为实例(或者更糟糕的是,作为 )变量,那么它绝对不是线程安全的,因为它随后在来自所有用户(会话)应用程序的所有请求(线程)之间共享。您只需要将它们作为方法局部变量分配,以保持它们的线程安全。所以:static

public class MyServlet extends HttpServlet {

    private Object thisIsNOTThreadSafe;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Object thisIsThreadSafe;

        thisIsNOTThreadSafe = request.getParameter("foo"); // BAD!! Shared among all requests!
        thisIsThreadSafe = request.getParameter("foo"); // OK, this is thread safe.
    } 
}

这基本上就是在开发考虑到线程安全性的 servlet 时需要考虑的全部内容。

然后是会话(HttpSession)属性,可以在来自同一用户的多个请求之间共享,但在现实世界中,您实际上不需要担心同步会话访问。您通常只将用户特定的数据放在那里,例如登录用户,用户特定的首选项,购物篮等。只需确保不要将纯请求范围的数据放在会话范围内。它将反映在同一会话中的多个浏览器窗口/选项卡中。

然后是应用程序(ServletContext)属性,这些属性在应用程序范围内的所有用户之间共享,但您通常只在那里放置常量和其他静态数据,例如webapp配置,DAO工厂,下拉列表内容等。顺便说一句,这一切都可以用ServletContextListener来完成,另请参阅此答案以获取基本示例。只需确保不要将纯请求或会话范围的数据放在应用程序范围内即可。


答案 2

推荐