<%@pagelanguage="java"import="java.util.*"pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPEHTMLPUBLIC"-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Servlet测试</title>
</head>
<body>
<ahref="<%=path%>/servlet/ServletTest">Servlet测试</a>
</body>
</html>
importjava.io.IOException;
importjava.io.PrintWriter;
importjavax.servlet.ServletException;
importjavax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
publicclassServletTestextendsHttpServlet {
intcount=0;
publicvoiddoGet(HttpServletRequest request, HttpServletResponse response)
throwsServletException, IOException {
response.setCharacterEncoding("gb2312");
PrintWriter out = response.getWriter();
out.println("servlet测试:"+this.count++);
}
}
当你访问你的工程,并点击a标签的链接的时候就进入到servlet,但是当你在servlet的页面一直刷新的时候,会发现打印的数字一直在增加,而且当你关闭浏览器的时候重新访问,还是会从你关闭的时候的数字继续累加。
我们来想一下是什么导致了这个原因:
1.可能变量是static的,只要是静态的就只会执行一次,也就只会一直用同一个
2.可能是一个application的全局变量,我们知道网页的访问量一般都是用application去记录的
3.有可能是同一个对象
那我们看一下,首先count不是static的,而且也不是application的,那么只有可能是同一个对象,下面我们来写一段代码去验证一下:
首先建立一个学生类:
publicclassStudent {
publicintage;
publicvoidadd(){
this.age++;
System.out.println("年龄是:"+this.age);
}
}
在建立一个测试类:
publicclassTestMain {
publicstaticvoidmain(String[] args) {
Student stu=newStudent();
stu.add();
stu.add();
stu.add();
}
}
创建一个学生的对象多次调用的时候就会在控制台打印:
当我们在创建一个对象的时候,那数据就会被覆盖,重新开始计数:
publicclassTestMain {
publicstaticvoidmain(String[] args) {
Student stu=newStudent();
stu.add();
stu.add();
stu.add();
System.out.println("====================");
Student stu1=newStudent();
stu1.add();
stu1.add();
stu1.add();
}
}
控制台结果:
所以我现在就把上面的servlet代码更改一下,我们把count从外面接收一下:
importjava.io.IOException;
importjava.io.PrintWriter;
importjavax.servlet.ServletException;
importjavax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
publicclassServletTestextendsHttpServlet {
intcount=0;
publicvoiddoGet(HttpServletRequest request, HttpServletResponse response)
throwsServletException, IOException {
response.setCharacterEncoding("gb2312");
PrintWriter out = response.getWriter();
String cou=request.getParameter("cou");
count=Integer.parseInt(cou);
try{
Thread.sleep(3000);
}catch(InterruptedException e) {
e.printStackTrace();
}
out.println("servlet测试:"+this.count++);
}
}
上面的延迟时间是为了实现并发的效果。
这样当我们访问的时候,我们就可以在浏览器传参,我们知道Get访问方式可以在浏览器传参
当我们同时访问浏览器的时候cou一个传5,一个传10
那就会在两个页面得到一个相同的数据,其中一个被另一个覆盖了
这就是servlet的线程不安全
所以我们只要把代码放到synchronized,代码如下:
importjava.io.IOException;
importjava.io.PrintWriter;
importjavax.servlet.ServletException;
importjavax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
publicclassServletTestextendsHttpServlet {
intcount=0;
publicvoiddoGet(HttpServletRequest request, HttpServletResponse response)
throwsServletException, IOException {
synchronized(this){
response.setCharacterEncoding("gb2312");
PrintWriter out = response.getWriter();
String cou=request.getParameter("cou");
count=Integer.parseInt(cou);
try{
Thread.sleep(3000);
}catch(InterruptedException e) {
e.printStackTrace();
}
out.println("servlet测试:"+this.count++);
}
}
}
希望有什么不好的多多交流。。。。。