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