当前位置:首页 > 开发 > 系统架构 > 架构 > 正文

多用户并发访问Servlet与线程同步

发表于: 2011-04-09   作者:com0606   来源:转载   浏览次数:
摘要: Servlet容器为了响应多个用户同时访问一个Servlet的HTTP请求,通常会为每个请求分配一个工作线程,这些工作线程并发执行同一个Servlet的service()方法。此时可能发生多线程对同一数据进行访问的情况。 public class Hello extends HttpServlet{ private String name; public void do
Servlet容器为了响应多个用户同时访问一个Servlet的HTTP请求,通常会为每个请求分配一个工作线程,这些工作线程并发执行同一个Servlet的service()方法。此时可能发生多线程对同一数据进行访问的情况。

public class Hello extends HttpServlet{
	private String name;
	
	public void doPost(HttpServletRequest request,HttpServletResponse response)
        throws ServletException,java.io.IOException{
		
		response.setContentType("text/html;charset=UTF-8");
		
		name = (String)request.getParameter("name");	//接收参数
		
		PrintWriter out = response.getWriter();
		out.println("<html><head><title>test</title></head><body>");
		out.println("你好"+name);
		out.println("</body></html>");
				
		out.close();
	}
}


如果多线程并发访问,会访问同一个实例变量,则会共用name,而出现用户得到数据不一致的现象。

解决办法:
1.将name设置为局部变量。
	
public class Hello extends HttpServlet{
	
	public void doPost(HttpServletRequest request,HttpServletResponse response)
        throws ServletException,java.io.IOException{
		
		response.setContentType("text/html;charset=UTF-8");
		
		String name = (String)request.getParameter("name");	//接收参数
		
		...
	}
}

每当一个线程执行doPost()时,在线程的堆栈中就会创建name这个局部变量,当线程执行完该方法,局部变量就结束生命周期。如果多个线程同时执行该方法,那么每个线程都拥有自己的局部变量。

2.使用Java同步机制对多线程同步
public class Hello extends HttpServlet{
	private String name;
	
	public void doPost(HttpServletRequest request,HttpServletResponse response)
        throws ServletException,java.io.IOException{
		
		response.setContentType("text/html;charset=UTF-8");
		
		synchronized(this){
			name = (String)request.getParameter("name");	//接收参数
            ...
		}
		...
	}
}

这样可确保在任意一时刻,只允许有一个工作线程执行doPost()中的同步代码块。只有当这个工作线程退出同步代码块时,其他工作线程才允许执行同步代码块。这使得任意时刻不会有两个线程同时操纵同一个实例变量,从而避免并发问题。

3.实现被废弃的SingleThreadModel接口
public class Hello extends HttpServlet implements SingleThreadModel{
  ...
}
如果实现此接口,则Servlet容器实现可以采用以下两种方式之一来运行Servlet:
1)在任意一时刻,只允许有一个工作线程执行Servlet的service()方法。如果有多个用户同时请求访问该Servlet,那么这些客户请求被放入等待队列,容器会依次响应等待队列中的每个客户请求。这种实现方式实际上禁止了多个客户端对同一个Servlet的并发访问。
2)Servlet容器为每个Servlet创建一个对象池,在这个池中存放了同一个Servlet类的多个实例。如果有多个用户同时请求访问该Servlet,Servlet容器会为每个请求分配一个工作线程,并且从对象池中取出一个空闲的Servlet实例,把它分配给工作线程。每个工作线程执行自己的Servlet实例的service()方法。这种实现方式表面上允许客户端对同一个Servlet并发访问,但实际上不同客户端访问的是同一个Servlet类的不同实例。
如果实例变量需要共享,用以进行计算,这种方法并不能有效的避免并发问题。

多用户并发访问Servlet与线程同步

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
曾经有个错误的认识,一直以为静态方法在多用户并发下会是排队等待,一个个执行,前些日子与朋友 单
本文将介绍用来控制资源同时访问个数的Semaphore工具类, 然后采用Semaphore给出一个泊车的实例,最后
本文将介绍用来控制资源同时访问个数的Semaphore工具类, 然后采用Semaphore给出一个泊车的实例,最后
<!---->   Servlet/JSP技术和ASP、PHP等相比,由于其多线程运行而具有很高的执行效率。由于
首先明确一点,各类书籍里面说synchronized锁住了相应的代码,即同步代码块,其实这是不准确的,真正
第一部分: 常用的集合类ArrayList、Map等在多线程操作同一对象时会发生不同步的线程而造成数据读取
在应用编程中,我们会遇到下面这样的调用模型。。。 当一个业务方法(begin)中顺序调用多个子业务
本文将介绍: Java线程基本操作(创建、等待等) Java线程同步原语(同步、互斥) 如果你对以上话题已了
锁永远是锁的对象!即使对加在static method方法上的所谓“锁住的是当前类”的锁,其实锁的也无非是C
锁永远是锁的对象!即使对加在static method方法上的所谓“锁住的是当前类”的锁,其实锁的也无非是C
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号