我们都知道servlet是线程不安全的,但是到底是怎么不安全的,我们今天来看一下
首先,我们先建立一个jsp去进行一下测试,看看servlet对于变量的测试
<%@ page language = "java" import = "java.util.*" pageEncoding = "UTF-8" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+ "://" +request.getServerName()+ ":" +request.getServerPort()+path+ "/" ;
%>

<! DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
< html >
< head >
< title > Servlet测试 </ title >
</ head >
< body >
< a href = " <%= path %> /servlet/ServletTest" > Servlet测试 </ a >
</ body >
</ html >
内部仅有一个a标签,下面写一个servlet
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ServletTest extends HttpServlet {
int count =0;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, 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的,那么只有可能是同一个对象,下面我们来写一段代码去验证一下:
首先建立一个学生类:
public class Student {

public int age ;
public void add(){
this . age ++;
         System. out .println( "年龄是:" + this . age );
    }
}
在建立一个测试类:
public class TestMain {

public static void main(String[] args) {
         Student stu= new Student();
         stu.add();
         stu.add();
         stu.add();
    }
}

创建一个学生的对象多次调用的时候就会在控制台打印:

wKioL1NYyD7hUtVFAAAKxUKQSh8859.png

当我们在创建一个对象的时候,那数据就会被覆盖,重新开始计数:
public class TestMain {

public static void main(String[] args) {
         Student stu= new Student();
         stu.add();
         stu.add();
         stu.add();
         System. out .println( "====================" );
         Student stu1= new Student();
         stu1.add();
         stu1.add();
         stu1.add();
    }
}

控制台结果:

wKiom1NYyIPSmQbEAAAQgXLvcFg927.png

所以我现在就把上面的servlet代码更改一下,我们把count从外面接收一下:
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ServletTest extends HttpServlet {
int count =0;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, 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

那就会在两个页面得到一个相同的数据,其中一个被另一个覆盖了

wKiom1NYyLeygS1zAAEVt2X27n0348.png

这就是servlet的线程不安全
所以我们只要把代码放到synchronized,代码如下:
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ServletTest extends HttpServlet {
int count =0;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, 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 ++);
         }
    }
}
希望有什么不好的多多交流。。。。。