Java servlet的每个实例与servlet中的每个servlet线程之间的区别?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2183974/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Difference between each instance of servlet and each thread of servlet in servlets?
提问by giri
Are there multiple instances of servlet class? As I hear "each instance of servlet" Can anybody elaborate on this?
servlet 类是否有多个实例?当我听到“servlet 的每个实例”时,有人可以详细说明一下吗?
采纳答案by BalusC
When the Servlet container starts, it:
当 Servlet 容器启动时,它:
- reads
web.xml
; - finds the declared Servlets in the classpath; and
- loads and instantiates each Servlet only once.
- 读
web.xml
; - 在类路径中找到声明的 Servlet;和
- 只加载和实例化每个 Servlet一次。
Roughly, like this:
大致是这样的:
String urlPattern = parseWebXmlAndRetrieveServletUrlPattern();
String servletClass = parseWebXmlAndRetrieveServletClass();
HttpServlet servlet = (HttpServlet) Class.forName(servletClass).newInstance();
servlet.init();
servlets.put(urlPattern, servlet); // Similar to a map interface.
Those Servlets are stored in memory and reused every time the request URL matches the Servlet's associated url-pattern
. The servlet container then executes code similar to:
这些 Servlet 存储在内存中,并在每次请求 URL 与 Servlet 的关联url-pattern
. 然后 servlet 容器执行类似于以下内容的代码:
for (Entry<String, HttpServlet> entry : servlets.entrySet()) {
String urlPattern = entry.getKey();
HttpServlet servlet = entry.getValue();
if (request.getRequestURL().matches(urlPattern)) {
servlet.service(request, response);
break;
}
}
The GenericServlet#service()
on its turn decides which of the doGet()
, doPost()
, etc.. to invoke based on HttpServletRequest#getMethod()
.
将GenericServlet#service()
其反过来决定其中doGet()
,doPost()
要调用基础上,等HttpServletRequest#getMethod()
。
You see, the servletcontainer reuses the same servlet instancefor every request. In other words: the servlets are shared among every request. That's why it's extremely important to write servlet code the threadsafe manner --which is actually simple: just do notassign request or session scoped data as servlet instance variables, but just as method local variables. E.g.
您会看到,servletcontainer为每个请求重用相同的 servlet 实例。换句话说:servlet 在每个请求之间共享。这就是为什么它是要编写servlet代码的线程安全的方式,可呈现其实很简单极为重要的:只是做不分配请求或会话范围的数据作为servlet实例变量,但正如方法的局部变量。例如
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.
}
}
回答by Bozho
No, there is only one instance of the servlet which is reused for multiple requests from multiple clients. This leads to two important rules:
不,只有一个 servlet 实例可重复用于来自多个客户端的多个请求。这导致了两个重要的规则:
- don't use instance variables in a servlet, except for application-wide values, most often obtained from context parameters.
- don't make methods
synchronized
in a servlet
- 不要在 servlet 中使用实例变量,除了应用程序范围的值,通常从上下文参数中获得。
- 不要
synchronized
在 servlet 中创建方法
(same goes for servlet filters and jsps)
(同样适用于 servlet 过滤器和 jsps)
回答by fastcodejava
There can not be multiple instances of servlet class. Even when there is one instance of the servlet, it is able to handle multiple requests. So it is wise not to use class level variables.
servlet 类不能有多个实例。即使只有一个 servlet 实例,它也能够处理多个请求。所以最好不要使用类级别的变量。
回答by Samuel Edwin Ward
According to the Java Servlet Specification Version 3.0 (pp. 6-7), there will be one instance per declaration per JVM, unless the servlet implements SingleThreadModel in which case there may be multiple instances per JVM.
根据 Java Servlet 规范版本 3.0(第 6-7 页),每个 JVM 的每个声明将有一个实例,除非 servlet 实现 SingleThreadModel,在这种情况下,每个 JVM 可能有多个实例。
回答by lcn
For those that know real JavaScript (not just a library of it), Servlets can be viewed as function objects. As functional objects, the main task of them is to do something, instead of to store some informationin their chests. There is no need to instantiate more than one instance of every such functional object, with the same rationale that Java class methods are shared among all instances of that class.
对于那些了解真正的 JavaScript(不仅仅是它的库)的人来说,Servlet 可以被视为函数对象。作为功能对象,它们的主要任务是做某事,而不是将一些信息存储在它们的胸膛中。不需要为每个这样的功能对象实例化一个以上的实例,这与 Java 类方法在该类的所有实例之间共享的基本原理相同。
回答by Saurabh Patil
Although there are already a few good answers, none of them spoke about a Java web application deployed in a distributed environment. This is a practical scenario where actually multiple instances of a single servlet are created. In a distributed environment you have a cluster of machines to handle the request and the request can go to any of these machines. Each of these machines should be capable to handle the request and hence every machine should have an instance of your MyAwesomeServlet in it's JVM.
尽管已经有一些很好的答案,但没有一个提到部署在分布式环境中的 Java Web 应用程序。这是一个实际的场景,其中实际上创建了单个 servlet 的多个实例。在分布式环境中,您有一组机器来处理请求,并且请求可以发送到这些机器中的任何一台。这些机器中的每一个都应该能够处理请求,因此每台机器都应该在它的 JVM 中有一个 MyAwesomeServlet 的实例。
So, the correct statement would be there is only one instance per JVM for every servlet, unless it implements SingleThreadModel.
因此,正确的说法应该是每个 servlet 的每个 JVM 只有一个实例,除非它实现了 SingleThreadModel。
SingleThreadModel in simple words says that you have to have only one thread per instance of Servlet, so basically you need to create one instance per coming request to handle it, which basically kills the whole concept of handling requests in a parallel fashion and isn't considered a good practice as the servlet object creation and initialization takes up time before it's ready to process the request.
SingleThreadModel 简单地说就是每个 Servlet 实例必须只有一个线程,所以基本上你需要为每个即将到来的请求创建一个实例来处理它,这基本上扼杀了以并行方式处理请求的整个概念,而不是被认为是一种很好的做法,因为 servlet 对象的创建和初始化在它准备好处理请求之前需要一些时间。