由于servlet是个线程池,而且是非线程安全,所以当压力过大的时候,容易导致一些奇怪的现象。
如下面的代码
// instanceconcurrenttest.jsp
<%@ page contentType="text/html;charset=GBK" %>
<%!
//定义实例变量
String username;
String password;
java.io.PrintWriter output;
%>
<%
//从request中获取参数
username = request.getParameter("username");
password = request.getParameter("password");
output = response.getWriter();
showUserInfo();
%>
<%!
public void showUserInfo() {
//为了突出并发问题,在这儿首先执行一个费时操作
int i =0;
double sum = 0.0;
while (i++ < 200000000) {
sum += i;
}
output.println(Thread.currentThread().getName() + "<br>");
output.println("username:" + username + "<br>");
output.println("password:" + password + "<br>");
}
%>
在这个页面中,首先定义了两个实例变量,username和password。然后在从request中获取这两个参数,并调用showUserInfo()方法将请求用户的信息回显在该客户的浏览器上。在一个用户访问是,不存在问题。但在多个用户并发访问时,就会出现其它用户的信息显示在另外一些用户的浏览器上的问题。这是一个严重的问题。为了突出并发问题,便于测试、观察,我们在回显用户信息时执行了一个模拟的费时操作,比如,下面的两个用户同时访问(可以启动两个IE浏览器,或者在两台机器上同时访问):
a: http://localhost:8080/instanceconcurrenttest.jsp?username=a&password=123
b: http://localhost:8080/instanceconcurrenttest.jsp?username=b&password=456
如果a点击链接后,b再点击链接,那么,a将返回一个空白屏幕,b则得到a以及b两个线程的输出
如果是简单的将showUserInfo方法简单的synchronized并不能解决问题。(可以试一下)。
解决问题的办法是给方法中的变量传一个实例进取。
<%!
//定义实例变量
String username;
String password;
java.io.PrintWriter output;
%>
<%
//从request中获取参数
username = request.getParameter("username");
password = request.getParameter("password");
output = response.getWriter();
showUserInfo(username,password,output);
//showUserInfo();
%>
<%!
public void showUserInfo(String user ,String pass,java.io.PrintWriter _output) {
// public void showUserInfo() {
//为了突出并发问题,在这儿首先执行一个费时操作
int i =0;
double sum = 0.0;
while (i++ < 200000000) {
sum += i;
}
_output.println(Thread.currentThread().getName() + "<br>");
_output.println("username:" + user + "<br>");
_output.println("password:" + pass + "<br>");
}
%>
这样就可以解决问题。
但我有点想不明白的是java传参数是传得引用,可是这里如果是引用的话那和上面的代码效果应该一样。所以推断,传得是实例。
问题时解决了,但我不想继续得过且过,不知道我那里想错了,请各位指点。
上面的例子摘自:http://publish.it168.com/2005/1209/20051209002201_hezuo.shtml?cChanNel=11&cpositioncode=296&hezuo=2
分享到:
相关推荐
Servlet 线程安全问题是指在使用 Servlet 编程时,如果不注意多线程安全性问题,可能会导致难以发现的错误。Servlet/JSP 技术由于其多线程运行而具有很高的执行效率,但这也意味着需要非常细致地考虑多线程的安全性...
jsp 传参 servlet 接收中文乱码问题的解决方法 jsp 传参 servlet 接收中文乱码问题是一个经常遇到的问题,特别是在使用 Hibernate+Servlet 框架时。当我们在 jsp 页面传参到 servlet 时,中文字符经常会出现乱码...
- **编码与解码不匹配**:当JSP页面、Servlet或服务器配置的字符编码不一致时,中文字符在传输过程中可能被错误地编码或解码,从而导致乱码。 - **默认编码问题**:Java Web容器(如Tomcat)默认可能使用ISO-8859-...
解决Servlet的线程安全问题通常有以下几种策略: 1. **避免使用实例变量**:尽可能使用局部变量,局部变量只存在于方法的执行上下文中,不会被多个线程共享,因此不存在线程安全问题。 2. **使用同步控制**:通过`...
在探讨Servlet线程安全的解决方案之前,我们先来了解一下为何会出现线程安全问题。当多个线程同时访问同一个Servlet时,如果这些线程同时修改了Servlet中的共享资源(例如实例变量),那么就可能会导致数据不一致性...
Servlet是一种线程不安全的组件,它的线程不安全性体现在多线程环境下共享一个实例变量,导致线程安全问题。下面我们将从Servlet的工作原理说起,详细解释Servlet接收和响应客户请求的过程,并探讨Servlet线程不安全...
Servlet 是一个运行在服务器端的单实例多线程的服务器端 Java 应用程序。理解 Servlet 的生命周期和接受参数信息是掌握 Servlet 技术的关键。 Servlet 的生命周期 Servlet 的生命周期可以分为四个阶段: 1. 初始...
在Java Web开发中,`JSP (JavaServer Pages)`、`Servlet`以及`SQL`的交互是实现动态网页的关键技术。本话题主要关注如何通过`Servlet`处理分页查询,并将参数传递给`SQL`来实现数据库数据的翻页显示。下面我们将详细...
针对Servlet线程安全问题,通常有以下几种解决方案: 1. **使用局部变量**:尽量避免使用实例变量,转而使用局部变量,这样每个线程都会有自己的副本,不会出现数据冲突。 2. **同步机制**:利用Java的...
当第一个请求到达时,Tomcat会创建Servlet实例,后续的请求将复用同一个实例,这意味着多个线程可能同时访问Servlet的同一实例,从而引发线程安全问题。 Servlet线程池机制 Tomcat容器为了高效地处理请求,采用了一...
然而,现代Servlet容器更倾向于使用多实例策略来缓解单一线程模型带来的效率问题,即创建一个Servlet实例池,每个请求分配一个实例进行处理,处理完毕后实例返回池中等待下一次分配,以此平衡性能与线程安全。
为解决Servlet的线程安全问题,有以下几种策略: 1. **使用synchronized关键字**:可以通过在Servlet方法上添加`synchronized`关键字,确保同一时间只有一个线程能执行该方法,从而避免数据冲突。但这种方式会影响...
本文将深入探讨Servlet及其衍生框架Struts中的线程安全问题,并提出相应的解决方案。 #### 二、Servlet的多线程机制 Servlet的生命周期是由Web容器管理的。当客户端首次请求某个Servlet时,容器会根据`web.xml`...
Servlet-api.jar和jsp-api.jar是Java Web开发中两个非常重要的库文件,它们包含了Servlet和JSP(JavaServer Pages)的相关API,使得开发者可以构建动态Web应用程序。这两个文件通常由Java EE(Enterprise Edition)...
在本场景中,我们探讨的是如何使用JSP通过Ajax(Asynchronous JavaScript and XML)发送JSON(JavaScript Object Notation)数据到Java的Servlet,然后Servlet处理这些数据并返回JSON响应给JSP页面。这是一个典型的...
《Head First Servlet & JSP》是一本非常受欢迎的IT教程,专为准备SCWCD(Sun Certified Web Component Developer)认证的读者设计。本书以其独特的学习风格,深入浅出地介绍了Servlet和JSP(JavaServer Pages)这两...