【发布时间】:2011-08-02 11:23:19
【问题描述】:
我知道只有一个 servlet 实例(一个实例用于一个 servlet 基础)将在 Web 容器中可用。是否可以在 Web 容器中创建一个实例池?像数据库连接?如果我创建一个 servlet 实例池,那么我如何将其作为线程安全的? (但我研究过每个 servlet 只能创建一个 servlet 实例)。
【问题讨论】:
我知道只有一个 servlet 实例(一个实例用于一个 servlet 基础)将在 Web 容器中可用。是否可以在 Web 容器中创建一个实例池?像数据库连接?如果我创建一个 servlet 实例池,那么我如何将其作为线程安全的? (但我研究过每个 servlet 只能创建一个 servlet 实例)。
【问题讨论】:
我知道这是一个面试问题。我会这样回答:
您可以让 servlet 实现
SingleThreadModel以使容器创建一个包含同一 servlet 类的多个实例的池。最大池大小取决于所使用的容器,例如在 Tomcat 上,这是 20。但是,一个很大的但是,这个接口从 Servlet 2.4 开始就被弃用了!我们实际上应该以线程安全的方式编写 servlet,而不是将请求和/或会话范围的数据分配为 servlet 的实例变量。这样就可以安全地跨多个线程使用单个 servlet 实例(阅读:跨多个 HTTP 请求)。
【讨论】:
问题是,你为什么要这样做?
Servlet 容器为每个 servlet 声明实例化单个实例。这意味着,您可以拥有多个 servlet 实例,但您需要声明 servlet 的次数与您想要/需要的实例数一样多。这也带来了如何调用 servlet 的问题……它们需要映射到不同的路径。
您可以这样做的另一种方法是创建一个处理程序池,您的单个 servlet 可以调用这些处理程序。
关于如何使它们成为线程安全的:这取决于你想在这些处理程序中做什么。一般情况下很难告诉你。
如果您询问线程安全池,您可以使用 Apache Commons Pool 库或 Java 中的一些 BlockingQueue(例如 LinkedBlockingQueue):队列可能包含您的处理程序。 Servlet 将take() 第一个处理程序,使用它,并在完成后将put() 返回。 (当然这只是一个例子,实现池的方法有很多)。
但是...确保您真的需要这样的设计,也许您的要求可以通过更简单的方式来满足? (如果您的目标是限制同时处理的并发请求的数量,也许只限制容器中 HTTP 工作线程的数量就足够了?或者如果这还不够,您可以使用限制过滤器?)
【讨论】:
定义 servlet 池没有意义,因为 Servlet 本身不是线程。 Web 容器(例如 Tomcat)维护一个调用 Servlet 实例的线程池。因此,如果您想增加吞吐量(并发用户数),您必须增加 Web 容器的池大小。
【讨论】: