为什么Servlet不是线程安全的?

时间:2012-03-04 14:52:55

标签: servlets

我需要知道为什么servlet不是线程安全的?那是什么原因在Struts 2.0框架控制器servlet是线程安全的?

6 个答案:

答案 0 :(得分:41)

  

我需要知道为什么servlet不是线程安全的?

Servlet实例本质上不是线程安全的,因为Java编程语言通常具有多线程特性。 Java虚拟机支持多个线程执行相同的代码。对于具有多个处理器的计算机,这是一个很好的性能优势。这也允许多个并发用户执行相同的代码而不会相互阻塞。

想象一下具有4个处理器的服务器,其中普通的servlet每秒可处理1000个请求。如果该servlet是线程安全的,那么Web应用程序的行为就像它在具有1个处理器的服务器上运行,其中servlet每秒只能处理250个请求(好吧,它不像那样,但是你明白了。)

如果在使用servlet时遇到线程安全问题,那么它是你的错误,而不是Java或Servlet的错误。您需要修复servlet代码,使得请求或会话范围数据永远不会分配为servlet的实例变量。有关详细说明,请参阅How do servlets work? Instantiation, sessions, shared variables and multithreading

  

是什么原因在Struts 2.0框架控制器servlet中是线程安全的?

它不是线程安全的。您将Struts调度程序 servlet 过滤器与Struts操作混淆。每次请求都会重新创建struts操作。因此,每个请求都有自己的请求作用域Struts操作的实例。 Struts调度程序 servlet 过滤器不会将它们存储为自己的实例变量。相反,它将其存储为HttpServletRequest的属性。

答案 1 :(得分:16)

Servlet是普通的java类,因此不是线程安全的。

但是,如果您没有实例变量,Java类是Thread安全的。只有实例变量需要同步。 (实例变量是在类中声明的变量,而不是在其方法中。

方法中声明的变量是线程安全的,因为每个线程都创建自己的程序堆栈,并且函数变量在堆栈中分配。这意味着为每个线程创建方法中的变量,因此没有任何线程同步问题关联。

方法变量是线程安全的,类变量不是。

答案 2 :(得分:9)

每个servlet映射都有一个servlet实例;所有实例属性都在所有请求之间共享。访问这些属性必须考虑到这一点。

Struts 2操作(不是“控制器servlet”,它们既不是servlet也不是控制器)是按请求实例化的。动作属性只能由单个请求的线程访问。

答案 3 :(得分:1)

Servlet通常是多线程的。

Servlet容器通常通过为每个请求创建新的Java线程来管理并发请求。新线程被赋予对所请求的servlet的对象引用,该servlet通过同一线程发出响应。这就是为什么在编写servlet时设计并发性很重要的原因,因为多个请求可能由同一个servlet实例处理。

servlet容器处理servlet请求的方式取决于实现;他们可能使用单个servlet,他们可能使用servlet池,这取决于供应商的系统架构。

Struts 2 Action对象是针对每个请求实例化的,因此没有线程安全问题。

答案 4 :(得分:1)

Servlet不是线程安全的,但我们可以通过将该servlet类实现为SingleThreadModel来使其成为线程安全的 就像给定的下面的类定义一样,性能问题也会出现,那么更好的选择就是使用synchronized部分

public class SurveyServlet extends HttpServlet
                           implements SingleThreadModel
{
servlet code here..
...
}

答案 5 :(得分:0)

Servlet本身不是线程安全的。您可以通过使服务方法同步来使其成为线程安全的。 你需要实现SingleThreadInterface以使其成为线程安全的。