Java 线程安全Servlet

Java 线程安全Servlet,java,multithreading,jsp,servlets,thread-safety,Java,Multithreading,Jsp,Servlets,Thread Safety,我正在开发一个JSP MVC web应用程序。我对线程安全Servlet的概念感到困惑。下面是我的代码,请告诉我它是否线程安全。另外,请告诉我为什么它是线程安全的或不是线程安全的 JSP代码 <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Tr

我正在开发一个JSP MVC web应用程序。我对线程安全Servlet的概念感到困惑。下面是我的代码,请告诉我它是否线程安全。另外,请告诉我为什么它是线程安全的或不是线程安全的

JSP代码

 <%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Personal Profile</title>
</head>
<body>
    <form id="PersonalData" method="post" action="PersonalDataServlet">
        First Name:<input type="input" name="FirstNameField"><br>
        Last Name:<input type="input" name="LastNameField"><br>
        Email:<input type="input" name="EmailField">Without @ part<br>
        <input type="Submit" value="Submit Data">
    </form>
    <br>
    <br>
    <br>
    <%
        out.print(request.getAttribute("FullName") + "\n");
        out.print(request.getAttribute("EmailAddress"));
    %>
</body>
</html>
用于实际计算或业务逻辑的其他类

package Model;

public class WelcomeName {

    public String FullName;
    public String EmailAddress;

    public void Fullname(String FirstName, String LastName, String Email) {
        FullName = (FirstName + " " + LastName);
        EmailAddress = (Email + "@gmail.com");
    }

}

我在您提供的代码中没有看到线程安全问题。线程安全主要是代码如何使用共享数据的函数,因此我寻找

servlet类的实例变量,如果servlet容器使用相同的servlet实例为多个线程中的请求提供服务,则这些变量在线程之间共享

通过servlet上下文或会话对象共享的对象;及

servlet或JSP访问的任何类的静态变量

这些并不是共享数据可以采用的唯一形式,但正如您所介绍的那样,它们可能适用于您的web应用程序。您没有任何通过这些机制进行的数据共享,因此您的servlet和JSP是线程安全的


如果您确实访问了共享对象,这不会自动使您的代码成为非线程安全的,但是您需要通过适当的同步来保护您的访问,以确保它们的线程安全。作为一个功能问题,您还需要注意同步,以避免阻塞线程的时间过长。

您可以使用SingleThreadModel。您的servlet类实现了这个接口,在此之后,您的servlet是线程安全的

每个方法调用都为其分配了自己的堆栈帧,没有其他线程访问它。所有局部变量都在此堆栈帧上分配。对于WelcomeNameObject,它是在堆上创建的,但对它的唯一引用是在创建它的方法调用的堆栈框架上,并且在请求对象上,即使请求对象更改了WelcomeNameObject上的某些内容,方法调用也会在那时完成,因此没有冲突。其他线程没有机会获取对它的引用并对其进行更改,因此它是线程安全的

如果移动welcomeName变量的声明,使其成为servlet中的实例变量:

@WebServlet("/PersonalDataServlet")
public class PersonalDataServlet extends HttpServlet {

    private WelcomeName WelcomeNameObject;

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

那么结果将是不安全的。servlet容器保留一个线程池来执行请求,它将这些请求发送到servlet的同一个实例,因此并发请求可以修改servlet实例变量的内容。例如,一个线程可能会进入该方法,创建对象的新实例并将其分配给实例变量,然后填充它,然后另一个线程可以调用该方法并创建对象的新实例并将其分配给同一实例变量,因此,第一次调用将返回一个与刚创建的对象完全不同的对象。

您确实需要阅读多线程和线程安全的一般知识。C.f.Brian Goetz的Java并发性实践。简单的几节课回答这样的问题是不够的;您的输入最好访问codereview.stackexchange.com…非常感谢您的回复。请澄清一件事,包模型中的类WelcomeName是否与线程安全有关?因为这个类有实例变量。真正的工作是由WelcomeName类完成的,我在servlet类的doPost方法中创建了一个对象WelcomeNameObject,并使用servlet将数据输入/输出到html页面,真正的工作是由WelcomeName完成的。@WaleedKhan,是的,WelcomeNameObject类有实例变量,但这对于线程安全来说并不重要,因为该类的任何实例都不会通过我在回答中描述的任何方式在线程之间共享。当我说servlet类的实例变量时,我的意思就是——换句话说,PersonalDataServlet类的实例变量;在servlet类的doPost方法之外,它仍然是线程安全的吗?@WaleedKhan,方法的局部变量与线程安全没有直接关系。它们不是线程之间共享数据的工具。它提供了线程安全性,但牺牲了并发性。从ServletAPI2.4开始,SingleThreadModel就被弃用了,这是有充分理由的。
@WebServlet("/PersonalDataServlet")
public class PersonalDataServlet extends HttpServlet {

    private WelcomeName WelcomeNameObject;

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {