java servlet 线程_关于java:servlet的每个实例与servlet中每个servlet线程之间的区别?...

本问题已经有最佳答案,请猛点这里访问。

servlet类有多个实例吗?正如我听到的"servlet的每个实例"有人能详细解释一下吗?

不!Web容器只在第一次请求时通过调用newInstance()方法创建servlet的一个实例。

当servlet容器启动时,它:

读取web.xml;

在类路径中查找声明的servlet;以及

只加载和实例化每个servlet一次。

大致如此:

String urlPattern = parseWebXmlAndRetrieveServletUrlPattern();

String servletClass = parseWebXmlAndRetrieveServletClass();

HttpServlet servlet = (HttpServlet) Class.forName(servletClass).newInstance();

servlet.init();

servlets.put(urlPattern, servlet); // Similar to a map interface.

这些servlet存储在内存中,并在每次请求URL与servlet关联的url-pattern匹配时重复使用。servlet容器随后执行类似以下代码:

for (Entry entry : servlets.entrySet()) {

String urlPattern = entry.getKey();

HttpServlet servlet = entry.getValue();

if (request.getRequestURL().matches(urlPattern)) {

servlet.service(request, response);

break;

}

}

轮到GenericServlet#service()决定doGet()和doPost()中的哪一个。基于HttpServletRequest#getMethod()调用。

可以看到,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.

}

}

+ 1。我要补充的是,如果在web.xml中将同一个servlet类映射到两个不同的URL,那么将创建两个实例。但是,一般原则仍然适用,一个实例服务于多个请求。

@Balusc,只是想知道,有没有一种方法可以从Web应用程序访问启动的servlet集?

类中的变量thisIsNotThreadSafe是共享给不同的用户还是只共享给同一用户的不同页面?我的意思是,如果我在我的计算机上浏览这个页面,而你在你的计算机上运行,我们是否共享这个非线程安全的相同空间?谢谢。

是的,@closedow,如果您的意思是两个客户机都访问同一个JVM,那么应该只有一个servlet,因此私有财产thisIsNOTThreadSafe将在会话之间共享。即使您注销并再次登录。

您好,我的理解是这些servlet实例存储在JVM中,当请求出现时,servlet容器会在JVM中搜索这些实例。这是正确的吗?

以上3个步骤是否都在容器启动时运行?表示servlet在容器启动时初始化了吗?那么为什么我们要使用"启动时加载"?

@未知:stackoverflow.com/q/3106452

@asifmushtaq否,容器在启动时不预加载servlet。这个过程是相同的,只是它可能在第一次请求时发生,而不是在启动时发生。工具允许您清楚地知道,某些servlet应该在启动时加载,特别是以您希望它们初始化的顺序加载。

不,servlet只有一个实例,可用于来自多个客户机的多个请求。这导致了两个重要的规则:

不要在servlet中使用实例变量,应用程序范围的值除外,这些值通常是从上下文参数获得的。

不要在servlet中生成方法synchronized。

(servlet过滤器和jsp也是如此)

根据JavaServlet规范3版(pp.6-7),除非JavaRead模型实现每个JVM的多个实例,否则每个JVM每个声明将有一个实例。

servlet规范3。(第6-7页)关于单线程模型的第2.2.1节注释中指出,"本规范版本中不推荐使用单线程模型接口。"

@reva虽然该接口确实被弃用了,但几乎可以肯定,它将永远不会被删除,容器将无限期地支持它。一旦成为规范的一部分,就始终是规范的一部分。

虽然已经有一些好的答案,但他们中没有人谈到部署在分布式环境中的Java Web应用程序。这是一个实际的场景,其中实际创建了一个servlet的多个实例。在分布式环境中,您有一个机器集群来处理请求,并且请求可以转到这些机器中的任何一台。这些机器中的每一台都应该能够处理请求,因此每台机器都应该在它的JVM中有一个myawesomeservlet实例。

因此,正确的语句应该是每个servlet的每个JVM只有一个实例,除非它实现了singlethreadmodel。

简单来说,singlethreadmodel表示,每个servlet实例只能有一个线程,因此基本上需要为每个即将到来的请求创建一个实例来处理它,这基本上扼杀了以并行方式处理请求的整个概念,并且作为servlet对象的创建和初始化并不被认为是一个好的实践。在准备好处理请求之前需要花费一些时间。

如果你真的想变得更加学究(很明显你是这样做的),那么servlet的唯一性不是每个JVM而是每个上下文。您可以在多个上下文路径下(在一个或多个JVM中)自由地部署同一个应用程序,并且每个JVM都将具有该servlet的实例。

@克里斯托弗舒尔茨:我不太明白,你能给我指一些材料来更好地理解它吗?谢谢。

如果myawesomeservlet是应用程序战争的一部分,并且您将其部署到两个上下文(例如/foo和/bar中),那么您将不得不复制MyAwesomeServlet类定义,实际上,还必须同时在内存中复制MyAwesomeServlet的两个实例。因此,实际上每个JVM可以有多个servlet实例。注意,JVM认为这些是单独的类,因为它们是由单独的类加载器加载的。Servlet规范中需要一个单独的类加载器,一般来说,爪哇中的概念类="CultLoope+类"。

servlet类不能有多个实例。即使有一个servlet实例,它也能够处理多个请求。所以最好不要使用类级变量。

对于那些知道真正的javascript(不仅仅是它的库)的用户,servlet可以被看作是函数对象。作为功能对象,它们的主要任务是做一些事情,而不是在胸部存储一些信息。不需要实例化每个这样的函数对象的一个实例,其原理与Java类方法在该类的所有实例之间共享的原理相同。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值