【问题标题】:Thread in servletservlet 中的线程
【发布时间】:2013-09-27 11:59:03
【问题描述】:

在一个应用程序中,如果涉及多个 servlet,那么每次为不同的 servlet 创建一个新线程时

例如,我有 2 个 servlet,servlet 1 和 servlet 2 都从同一个 html 表单中获取 rquest,一个是通过锚标记,另一个是通过表单

当点击链接时,请求被发送到 servlet 1,它再次将请求分派到索引页面,并从那里提交表单,请求被发送到 servlet 2

那么是为 servlet 1 和 servlet 2 分别创建了 2 个线程,还是只创建了 1 个为两个 servlet 服务的线程??

【问题讨论】:

    标签: java multithreading servlets


    【解决方案1】:

    Servlet 容器的一般模式是使用一个Thread 来处理一个请求。

    例如,我有 2 个 servlet servlet 1 和 servlet 2 都在获取 来自同一个 html 表单的请求是通过锚标记和 另一个通过表单

    当您提交form 时,浏览器会发送一个HTTP 请求。你的服务器发送一个Thread 来处理它。想想它做这样的事情(实际上要复杂得多)

    final Servlet servlet = ...// which servlet is url-mapped to the request
    Runnable toRun = new Runnable(
        public void run() {
            servlet.service(request, response); // with exception handling of course
        }
    );
    Thread toDispatch = new Thread(toRun); // actually get it from pool, but for simplicity
    toDispatch.start();
    

    同样,如果您点击锚链接,您的浏览器会发送一个新的 HTTP 请求,并以相同的方式处理。

    Servlet 类实例在线程之间共享。

    【讨论】:

    • @Sotirious 感谢您的回复,实际上我使用 eclipse ide 构建了程序,并在两个 servlet 上显示了线程名称,它给出了相同的值。这是否意味着为一个会话创建一个线程并且它用于为特定会话中涉及的所有 servlet 提供服务??
    • @anubhav 那是因为 Servlet 容器正在使用 Thread 池。当请求进来时,会从池中获取一个Thread 来处理它。当请求完成并返回响应时,Thread 将返回到池中,可供将来的请求使用。它与http会话无关,与Servlet无关。
    • 所以这意味着有可能使用同一个线程来服务另一个servlet??但是对于所有的 servlet,一个请求将有一个会话,这样就可以在另一个 servlet 的一个 servlet 中使用一个会话属性集。
    • @anubhav 对于每个请求,容器将创建HttpServletRequest(可能绑定到HttpSession 对象)和HttpServletResponse 对象。这些被提供给在处理Thread 中使用的servlet。这是从你那里抽象出来的。您通常只需要关心您的 servlet。 Thread 实例可用于处理任何 servlet 的任何请求。
    • 好的,感谢您的帮助并消除了我的疑虑,我想知道我的上述评论是否意味着有可能使用相同的线程来服务另一个 servlet?但是对于所有的 servlet,将有一个请求会话,以便可以使用在另一个 servlet 中的一个 servlet 中设置的一个会话属性是否正确。谢谢!!!
    【解决方案2】:

    当一个请求到达 Servlet Container(例如:Tomcat、WAS)时,它通常会从 ThreadPool 中随机选择一个线程,并且在整个请求生命周期中,接收到的请求将由所选线程处理。换句话说,从 UI 层到服务层再到数据层执行相同的线程。并且不能保证在随后的请求中分配相同的线程,即使您单击相同的链接反过来将请求提交给相同的 servlet。据说在即时请求中,Container 可能会选择相同的线程。

    如果要测试,请在 Servlet 中打印线程名称并多次提交请求。在您的示例中,多次单击锚链接并查看结果。

    回答您的问题: 如上所述,首先不会在每次请求到达时都创建一个新线程。 Servlet2 可能会使用相同的线程。

    【讨论】:

    • 实际上我使用 eclipse ide 构建了程序,并在两个 servlet 上显示了线程名称,它给出了相同的值。这是否意味着为一个会话创建了一个线程,它用于服务所有特定会话中涉及的 servlet??
    • 不!您可能还想尝试让线程休眠一段时间,并在前一个请求(或线程)唤醒之前从另一个窗口提交一个新请求。顺便说一句,您使用的是哪个应用程序服务器?
    【解决方案3】:

    对 Web 服务器的每个请求都由线程池中的一个新线程提供服务。 servlet 实例在请求之间共享,即线程。所以好的设计实践是在 servlet 中没有全局变量,否则会看到竞争条件。

    【讨论】:

    • 感谢您的回复,servlet 是根据 web.xml 中的启动值加载加载并在此之后实例化,但如果未提供,则在收到第一个请求并执行 init 方法时加载并实例化它只有一次初始化。一个不应该有全局变量,如会话或请求数据作为 servlet 实例,因为它将由所有线程共享。对于每个新请求,都会创建一个新线程。我在问如果我会发生什么情况上面已经描述过了。
    • 对于您的情况,这是一个新请求,因此将由线程处理。但我们不应该为此烦恼。
    【解决方案4】:
    1. 每个 http 请求都在一个单独的线程中处理,创建线程会增加一些开销,因此服务器会维护一个线程池,并且当请求进入时,它们只是重用一个空闲线程来处理该请求。
    2. 如果您在一个 servlet 中创建会话并设置会话属性,那么对于该会话,可以在任何其他 servlet 中访问该会话属性。

    【讨论】:

      猜你喜欢
      • 2011-12-02
      • 1970-01-01
      • 1970-01-01
      • 2014-06-30
      • 1970-01-01
      • 2016-08-24
      • 2012-02-10
      • 2012-02-18
      • 2020-05-25
      相关资源
      最近更新 更多