serverlet线程安全吗

本文探讨了Servlet的线程安全问题,通过一个示例展示了如何使用同步机制解决线程安全问题,并强调了全局变量和静态变量是导致线程不安全的主要原因。
本文属于转载:http://www.cnblogs.com/itTeacher/archive/2012/11/14/2769822.html

这个问题,在网上没有看到一个确切的答案,所以我们来分析一下:
首先什么是线程安全?
引用概念:如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。

那么我们都知道servlet是多线程的,同时一个servlet实现类只会有一个实例对象,也就是它是Singleton的,所以多个线程是可能会访问同一个servlet实例对象的。

每个线程都会为数据实例对象开辟单独的引用,那么servlet会是线程安全的吗?

要判断是否是线程安全,我们需要知道线程安全问题是由什么引起的。
搜索得到答案:线程安全问题都是由全局变量及静态变量引起的。
看到这个答案,突然想起很多年前调查过的一个bug, 那时我们系统中遗留的代码中写了很多全局变量,有一次发布后,客户反馈,当有多人同时进行某个操作时,我们的数据出了问题,那时我们调查后的结果就是:多人同步操作时,有些全局变量的值不对了,之后我们专门设一个人花了很多工夫来将所有全局变量都改成了局部变量了,并且项目要求以后不允许用全局变量。原来那时侯我就已经碰到过线程不安全的情况了啊,不过处理方式或者不用全局,或者加入同步,若加入同步同时也要考虑一下对程序效率会不会产生影响。

由此可知,servlet是否线程安全是由它的实现来决定的,如果它内部的属性或方法会被多个线程改变,它就是线程不安全的,反之,就是线程安全的。

在网上找到一个例子,如下:

public class TestServlet extends HttpServlet {
     private int count = 0;  
      
     @Override
     protected void service(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
         response.getWriter().println("<HTML><BODY>");
         response.getWriter().println(this + " ==> ");
         response.getWriter().println(Thread.currentThread() + ": <br>");
         for(int i=0;i<5;i++){
             response.getWriter().println("count = " + count + "<BR>");
             try {
                 Thread.sleep(1000);  
                 count++;  
             } catch (Exception e) {
                 e.printStackTrace();
             }
         }
         response.getWriter().println("</BODY></HTML>");
     }
 }



当同时打开多个浏览器,输入http://localhost:8080/ServletTest/TestServlet时,他们显示的结果不同,这就说明了对于属性count来说,它是线程不安全的,
为了解决这个问题,将代码重构,如下:

public class TestServlet extends HttpServlet {
      private int count = 0;  
      private String synchronizeStr = "";
      @Override
     protected void service(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
         response.getWriter().println("<HTML><BODY>");
         response.getWriter().println(this + " ==> ");
         response.getWriter().println(Thread.currentThread() + ": <br>");
         synchronized (synchronizeStr){
             for(int i=0;i<5;i++){
                 response.getWriter().println("count = " + count + "<BR>");
                 try {
                     Thread.sleep(1000);  
                     count++;  
                 } catch (Exception e) {
                     e.printStackTrace();
                 }
             }
         }
         response.getWriter().println("</BODY></HTML>");
     }
 }
### Java Servlet 开发概述 Java Servlet 是 Java Web 开发的核心技术之一,它属于动态资源,主要用于处理客户端的请求并生成响应内容。Servlet 是 Java EE 规范的一部分,运行在支持 Servlet 容器(如 Apache Tomcat、Jetty 或 JBoss)的服务器上。Servlet 提供了一种基于 Java 的机制来扩展服务器的功能,通常用于构建动态网页或提供 RESTful API 服务。 ### Servlet 的生命周期 Servlet 的生命周期由容器管理,主要包括以下三个阶段: 1. **加载和实例化**:当容器启动或首次接收到针对某个 Servlet 的请求时,会加载该 Servlet 类并创建其实例。 2. **初始化(init 方法)**:容器调用 `init()` 方法进行初始化,此方法仅在 Servlet 生命周期中执行一次。 3. **服务(service 方法)**:每次客户端请求到达时,容器都会调用 `service()` 方法处理请求并生成响应。该方法会根据请求类型(如 GET、POST)调用相应的 `doGet()` 或 `doPost()` 方法。 4. **销毁(destroy 方法)**:当容器决定卸载 Servlet 时(如服务器关闭或应用重新部署),会调用 `destroy()` 方法释放资源。 ### Servlet 接口和类 Java 提供了多个与 Servlet 相关的接口和类,其中最核心的是: - **Servlet 接口**:定义了 Servlet 的基本行为,包括 `init()`、`service()` 和 `destroy()` 方法。 - **GenericServlet 类**:实现了 `Servlet` 接口,并提供了通用的实现,适用于非 HTTP 协议的 Servlet。 - **HttpServlet 类**:继承自 `GenericServlet`,专门用于处理 HTTP 请求,提供了 `doGet()`、`doPost()` 等方法。 ### Servlet 的配置方式 Servlet 可以通过以下两种方式进行配置: 1. **使用 `web.xml` 配置**:在传统的 Java Web 应用中,`web.xml` 文件用于定义 Servlet 映射关系。例如: ```xml <servlet> <servlet-name>HelloServlet</servlet-name> <servlet-class>com.example.HelloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping> ``` 2. **使用注解配置(Servlet 3.0+)**:从 Servlet 3.0 开始,可以使用 `@WebServlet` 注解简化配置。例如: ```java @WebServlet("/hello") public class HelloServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { response.getWriter().write("Hello, Servlet!"); } } ``` ### Servlet 的应用场景 Servlet 在实际开发中具有广泛的应用场景,主要包括: - **处理网页请求**:接收来自浏览器的 HTTP 请求,并返回动态生成的 HTML 页面。 - **处理表单数据**:解析用户提交的表单数据,执行相应的业务逻辑。 - **构建 RESTful API**:结合 JSON 或 XML 格式的数据交换,提供前后端分离的 Web 服务。 ### 示例:处理表单提交 以下是一个简单的 Servlet 示例,用于处理 HTML 表单提交的 POST 请求: ```java @WebServlet("/submit") public class FormServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String username = request.getParameter("username"); String password = request.getParameter("password"); // 简单验证逻辑 if ("admin".equals(username) && "123456".equals(password)) { response.getWriter().write("登录成功!"); } else { response.getWriter().write("用户名或密码错误!"); } } } ``` 对应的 HTML 表单如下: ```html <form action="submit" method="post"> 用户名:<input type="text" name="username"><br> 密码:<input type="password" name="password"><br> <input type="submit" value="提交"> </form> ``` ### 示例:异步处理 从 Servlet 3.0 开始,引入了异步处理功能,允许 Servlet 在不阻塞线程的情况下处理请求。这对于长时间运行的任务(如数据库查询、外部 API 调用)非常有用。 ```java @WebServlet(urlPatterns = "/async", asyncSupported = true) public class AsyncServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { final AsyncContext asyncContext = request.startAsync(); new Thread(() -> { try { // 模拟耗时操作 Thread.sleep(2000); asyncContext.getResponse().getWriter().write("异步处理完成!"); asyncContext.complete(); } catch (Exception e) { e.printStackTrace(); } }).start(); } } ``` ### POM 依赖示例 在使用 Maven 构建 Java Web 项目时,需要添加相应的依赖。以下是一个典型的 `pom.xml` 配置片段: ```xml <dependencies> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.3.1</version> <scope>provided</scope> </dependency> </dependencies> ``` ### 总结 Java Servlet 是 Java Web 开发的基础组件之一,具有灵活的生命周期管理和强大的请求处理能力。通过合理的配置和使用,Servlet 可以满足从简单的表单处理到复杂的 RESTful API 构建等多种需求。随着 Servlet 规范的不断演进,其异步处理、注解配置等新特性进一步提升了开发效率和系统性能。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值