当服务器启动的时候,服务器的引擎就会创建一个Servlet的实例对象。系统只会创建一个直到服务区停止。每次请求都会开启一个新的线程进行处理,每次都会访问该对象的 service方法。当设计到共享资源的时候就会出现线程安全的问题。
/**
* Servlet implementation class ServletDemo1
*/
public class ServletDemo1 extends HttpServlet {
private static final long serialVersionUID = 1L;
int num=1;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
num++;
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
}
System.out.println(num);
response.getWriter().append(num+"");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
不同请求,不同线程都用到了 num 这个变量,所以会出现线程安全的问题。
解决办法1
/**
* Servlet implementation class ServletDemo1
*/
public class ServletDemo1 extends HttpServlet {
private static final long serialVersionUID = 1L
int num=1;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//同步鎖 锁住这个对象 当
synchronized (this) {
num++;
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
}
System.out.println(num);
response.getWriter().append(num+"");
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
加上锁就行了。当有人访问该对象的时候,锁住。执行完后进行释放次个锁,给别人用再 。就不会涉及到线程安全的问题了。
解决办法2
public class ServletThreadPoolDemo extends HttpServlet implements SingleThreadModel{
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().append("Served at: ").append(request.getContextPath());
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
让 servlet去实现SingleThreadModel接口(标记性接口,不用实现任何东西) 就标注下次servlet 访问的方式是单线程的访问 ,不存在并发的现象了。但是次接口目前已经废除,不建议使用。