【问题标题】:In Java, How do I make sure my web application is thread safe?在 Java 中,如何确保我的 Web 应用程序是线程安全的?
【发布时间】:2011-01-15 10:45:11
【问题描述】:

如何确保我的 java servlets web 应用程序是线程安全的?对于会话变量、类的静态变量或其他任何可能成为线程安全问题的东西,我需要做什么?

【问题讨论】:

    标签: java servlets jakarta-ee


    【解决方案1】:

    事实:在 webapp 的生命周期中只有 1 个 servlet 实例。它在 webapp 启动时创建,在 webapp 关闭时销毁。粗略解释请参见this answer

    因此,它在所有请求(线程)之间共享。如果您将请求或会话范围的数据分配为实例(或更糟糕的是,作为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 完成,另请参阅this answer 以获取基本示例。您只需要确保不将纯请求或会话范围的数据放入应用程序范围。

    【讨论】:

    • 一个关于“Web 应用程序生命周期中的一个 servlet”的问题 - 我认为这是一个池化对象,因此 可能 servlet 引擎根据负载自行决定不止一个.这不是真的吗?
    • 仅当它实现(根据已弃用的 Servlet 2.4)SingleThreadModel
    • @BalusC:非常感谢先生,这个答案终于帮助了我。我删除了我的问题并赞成您的回答。 Java 中没有像您这样的人。再次感谢一百万。
    【解决方案2】:

    【讨论】:

    • 我认为第 4 项几乎取代了(覆盖)1-3。 :)
    • 嗯,需要一些基础知识才能好好思考
    【解决方案3】:

    哇,这是一个加载的问题。

    简单地说,您需要确保对任何共享数据的访问都经过仔细同步。例如,您可能希望使用互斥锁或同步函数同步对静态变量的访问。

    请注意,如果您需要同时修改多个共享资源的原子事务,您可能还需要在更高级别进行同步。

    设计一个并发应用程序并不简单,而且没有灵丹妙药(很遗憾)。我强烈推荐《Java Concurrency in Practice》一书,了解有关编写安全并发代码的更多信息。

    【讨论】:

      【解决方案4】:

      您的意思是在上下文中与任何其他 java 应用程序相反?真的没有太大区别。对 servlet 的每个请求都会导致容器发出一个新线程来处理它,因此 servlet 中的实例变量必须是线程安全的。最好使用 doGet / doPost() 方法中的局部变量来处理您的所有业务。我能想到一个问题。对于会话变量,用户可能会打开两个浏览器窗口,它们都指向您的应用程序。在这种情况下,您还需要注意会话范围的线程安全。

      【讨论】:

        猜你喜欢
        • 2012-07-08
        • 2014-09-19
        • 1970-01-01
        • 2015-07-02
        • 1970-01-01
        • 1970-01-01
        • 2012-03-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多