【问题标题】:How can only one servlet instance exist in multiple threads? [closed]多线程中怎么可能只有一个 servlet 实例? [关闭]
【发布时间】:2014-08-13 09:16:28
【问题描述】:

通常,容器中只有一个特定 servlet 的实例。这个 servlet 被重用于每个请求。但是,默认情况下,每个 servlet 请求都在不同的线程中运行。例如,如何在对 doPost(request, response) 的两个不同调用中只存在一个扩展 HttpServlet 的 servlet 实例?

我想确认是否有两个堆栈为此使用一个堆。

【问题讨论】:

  • 无论你有多少个HttpServlet 实例——每次调用doPost 都会有它的私有堆栈,但所有调用都使用一个堆。这对于 Java 中的每个方法调用都是一样的。
  • 我不确定您的要求。如果您对如何由多个线程共享同一个 servlet 实例有疑问,这几乎就像您实例化一个对象,创建多个线程并将相同的对象实例传递给所有这些线程(我不知道 servlet 框架的内部结构给你一个准确的解释)。
  • watery 说了什么。实例化 servlet 以及创建和管理访问该实例的线程由 Servlet 容器完成。所以你不必担心。而且所有线程都有自己的栈,只有一个堆。
  • @isnot2bad 除非我们实现 SingleThreadModel 接口,否则容器可能会在容器的每个 JVM 中实例化该 servlet 的多个实例。
  • 每个线程都有自己的堆栈。这与 Servlet 甚至 Java 无关:对于每个设计的线程实现都是如此。

标签: java multithreading tomcat servlets


【解决方案1】:

Servlet Specification #2.2 声明:

对于不在分布式环境中托管的 servlet(默认), servlet 容器每个 servlet 只能使用一个实例 宣言。但是,对于实现 SingleThreadModel 的 servlet 接口,servlet 容器可以实例化多个实例以 处理繁重的请求负载并将请求序列化到特定的 实例。

如果 servlet 作为应用程序的一部分进行部署 在部署描述符中标记为可分发,容器可以 每个 Java Virtual 每个 servlet 声明只有一个实例 机器 (JVM)。但是,如果 servlet 在可分发的应用程序中 实现了 SingleThreadModel 接口,容器可以 在每个 JVM 中实例化该 servlet 的 多个实例 容器。

所以,使用 SingleThreadModel 就可以了。

另外,Creating Servlets 声明

默认情况下,servlet 不是线程安全的。单一的方法 servlet 实例通常同时执行多次 (直到可用内存限制)。 每次执行都发生在一个 不同的线程,尽管 servlet 中只存在一个 servlet 副本 引擎。

所以,你应该处理你的情况下的同步;

【讨论】:

  • 很好,但请注明出处。是 Servlet 规范吗?
  • 引用它。仅链接不是引用。我已经独立确定它是 Java Servlet 规范第 2.2 节。该信息应出现在您的答案中。
  • servlet 容器中可以有多个给定 Servlet 类的实例。请参阅我对 Servlet 规范的引用和来源的回答。
  • @icza 仅当您使用 SingleThreadModel 或提供多个声明时。
【解决方案2】:

Servlet 由 Servlet 容器实例化,您无法对其进行显式控制。

您不能强制在 Servlet 容器中只有 1 个特定 Servlet 的实例(尽管通常情况会如此);至少不是以官方方式,因为 Servlet API 没有提供任何方法来做到这一点。一些容器实现可能会为此提供任意 API,但我不会指望它。

而是让您的 Servlet 实现不依赖于有多少实例(例如,不要使用静态属性)。

更新:

引用Servlet specification 2.3 部分 #2.3.1:

请务必注意,可以有多个实例 在 servlet 容器中给定 Servlet 类。例如,这可以 发生在有多个 servlet 定义使用 具有不同初始化参数的特定 servlet 类。这 当 servlet 实现 SingleThreadModel 时也会发生 接口和容器创建一个 servlet 实例池以 使用。

【讨论】:

  • 大错特错。请参阅 Servlet 规范 2.2。
  • @EJP 我刚刚检查了规范,它清楚地指出特定 Servlet 可以有多个实例。请检查我更新的答案并告诉我为什么它是“大错特错”。
  • 这里的另一个答案中引用了它。除非您使用已弃用的 SingleThreadModel,否则“Servlet 容器必须在每个 Servlet 声明中仅使用一个实例”。因此,如果您不使用 SingleThreadModel 并且只有一个 Servlet 声明,则保证您只会获得一个实例。因此,您的第一句话和第二句话是错误的。 QED
  • 是的,如果我们将所有布尔变量设为假并检查它们的逻辑 OR'ed 值,它将是假的。SingleThreadModle 可能已被弃用,但仍然可以使用。另一方面,不推荐使用多个 servlet 声明。提问者没有将问题缩小到一个声明,所以我说的是真的。
  • 你好像没看懂你自己的引用,我也没说布尔变量,但是你说没有办法保证只有一个实例,规范提供你错了。你在这里没有多大意义。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-05-02
  • 2013-06-02
  • 2012-05-03
  • 1970-01-01
  • 2011-12-25
  • 2012-10-23
  • 2013-01-10
相关资源
最近更新 更多