测试Servlet是否线程安全
测试代码
package com.servlet.study; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ThreadSafeTestServlet extends HttpServlet{ /** * */ private static final long serialVersionUID = -5678315968996207090L; private String name; @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); resp.setCharacterEncoding("utf-8"); // TODO Auto-generated method stub System.out.println(this+":"+Thread.currentThread()); name = req.getParameter("user"); try { Thread.sleep(2000); } catch (InterruptedException e1) { // TODO Auto-generated catch block } resp.getWriter().println("用户名:"+name);; System.out.println("Counter = "+name); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doPost(req, resp); } }
页面请求:
请求1:http://localhost:8080/TESTWeb/thread?user=lisi
请求2:http://localhost:8080/TESTWeb/thread?user=wangw
输出结果:
com.servlet.study.ThreadSafeTestServlet@5dcc783c:Thread[http-nio-8080-exec-27,5,main]
com.servlet.study.ThreadSafeTestServlet@5dcc783c:Thread[http-nio-8080-exec-24,5,main]
Counter = wangw
Counter = wangw
请求1的输出,被请求2的name改写了,用户lisi的页面显示wangw的信息。
结论:
1、Servlet对象是一个无状态的单例对象(Singleton),因为请求多次,打印出来的hashcode值都相同。
2、Servlet在不同的线程池中运行,如上的Thread[http-nio-8080-exec-27和 24 区分出不同的线程执行了同一段Servlet逻辑代码。
3、name变量在不同的线程中共享,且它的值被不同的线程修改。输出时,已被其它线程修改后的值。
也就是说,其它线程会篡改当前线程中实例变量的值,针对这些对象的访问不是线程安全的。
解决方式一:
使用局部变量,代替全局变量。
package com.servlet.study; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ThreadSafeTestServlet extends HttpServlet{ /** * */ private static final long serialVersionUID = -5678315968996207090L; @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String name; resp.setContentType("text/html"); resp.setCharacterEncoding("utf-8"); // TODO Auto-generated method stub System.out.println(this+":"+Thread.currentThread()); name = req.getParameter("user"); try { Thread.sleep(2000); } catch (InterruptedException e1) { // TODO Auto-generated catch block } resp.getWriter().println("用户名:"+name);; System.out.println("Counter = "+name); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doPost(req, resp); } }
输出:
com.servlet.study.ThreadSafeTestServlet@53a2686d:Thread[http-nio-8080-exec-44,5,main]
com.servlet.study.ThreadSafeTestServlet@53a2686d:Thread[http-nio-8080-exec-39,5,main]
Counter = wangw
Counter = lisi
解决方式二:
使用synchorized关键字,保证一次只有一个线程访问保护的区域块。
private String name; @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); resp.setCharacterEncoding("utf-8"); // TODO Auto-generated method stub System.out.println(this+":"+Thread.currentThread()); synchronized(this){ name = req.getParameter("user"); try { Thread.sleep(2000); } catch (InterruptedException e1) { // TODO Auto-generated catch block } resp.getWriter().println("用户名:"+name);; System.out.println("Counter = "+name); } }
页面请求:
http://localhost:8080/TESTWeb/thread?user=lisi
http://localhost:8080/TESTWeb/thread?user=wangw
输出结果:
信息: Reloading Context with name [/TESTWeb] is completed
com.servlet.study.ThreadSafeTestServlet@3fadc5ba:Thread[http-nio-8080-exec-8,5,main]
com.servlet.study.ThreadSafeTestServlet@3fadc5ba:Thread[http-nio-8080-exec-4,5,main]
Counter = wangw
Counter = lisi
相关推荐
Servlet 线程安全问题 Servlet 线程安全问题是指在使用 Servlet 编程时,如果不注意多线程安全性问题,可能会导致难以发现的错误。Servlet/JSP 技术由于其多线程运行而具有很高的执行效率,但这也意味着需要非常...
Servlet线程安全问题详解 在Java Web开发中,Servlet是一个重要的组件,用于处理HTTP请求。然而,Servlet在多线程环境下的线程安全问题是一个不容忽视的话题。在Servlet的生命周期中,Tomcat容器会根据需求实例化...
#### 三、Servlet线程安全问题分析 线程安全问题是由于Servlet中实例变量的使用不当导致的。在多线程环境中,如果多个线程同时修改相同的实例变量,则可能导致数据不一致性问题。例如,在上面给出的`ConcurrentTest...
#### 一、理解Servlet线程安全问题 Servlet是Java平台上的一个重要的Web组件模型,用于处理HTTP请求并返回响应。每当客户端向服务器发送请求时,服务器会创建一个线程来处理这个请求。由于Servlet是单例模式实现的...
### Servlet线程安全问题实例分析 以一个简单的Servlet为例,该Servlet接收用户请求,读取参数,并输出结果: ```java public class Test extends HttpServlet { private static final long serialVersionUID = 1...
Servlet和Struts Action是两种常见的Java Web开发组件,它们在多线程环境下运行时可能存在线程安全问题。线程安全是指在多线程环境中,一个类或者方法能够正确处理多个线程的并发访问,保证数据的一致性和完整性。 ...
#### 三、Servlet线程安全问题 线程安全问题主要发生在Servlet中使用实例变量时。当多个线程并发访问同一个Servlet实例时,如果这些线程试图同时修改实例变量,就可能发生数据不一致的情况。以下通过一个具体的示例...
在讨论了Servlet线程安全问题的代码实现后,让我们来总结一下Servlet线程安全问题的几个要点: 1. 线程安全问题产生的原因:在多用户环境下,多个线程同时访问和修改共享资源(如Servlet中的`ticket`变量)时,如果...
Servlet是一种线程不安全的组件,它的线程不安全性体现在多线程环境下共享一个实例变量,导致线程安全问题。下面我们将从Servlet的工作原理说起,详细解释Servlet接收和响应客户请求的过程,并探讨Servlet线程不安全...
Servlet线程同步计数器实验是Java Web开发中一个重要的实践课题,主要涉及到Servlet容器如何处理并发请求以及如何确保在多线程环境下的数据一致性。在这个实验中,我们将深入理解Servlet生命周期、线程模型以及线程...
4. **避免在Servlet中创建额外线程**:由于Servlet本身已具备多线程特性,额外创建线程可能会引入复杂的线程安全问题,除非有特殊需求。 5. **对外部资源的线程安全操作**:在多个Servlet中对同一外部资源(如文件...
在这个场景下,可能的问题可能是由于Servlet在处理高并发请求时,由于多线程并发访问共享资源导致的线程安全问题。 在Java Web环境中,Servlet容器(如Tomcat、Jetty等)会为每个HTTP请求创建一个新的线程来处理,...
5. **Servlet线程安全问题**: Servlet容器通常会为每个请求创建一个新的线程,因此,Servlet实例默认是线程安全的。但是,如果在Servlet中定义了成员变量,需要考虑多线程环境下可能产生的并发问题。 6. **...