`
com0606
  • 浏览: 60954 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

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

阅读更多
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类的不同实例。
如果实例变量需要共享,用以进行计算,这种方法并不能有效的避免并发问题。
分享到:
评论
3 楼 com0606 2011-08-27  
Servlet的单例不由class来决定,而是由在web.xml里配置的servlet-name来决定。也就是说每一个servlet-name只有1个单例。当你有3个不同的serlvet-name指定了相同的1个servlet-class时,容器会产生3个不同的servlet object。
2 楼 com0606 2011-04-09  
s929498110 写道
 

第二个方法行吗?

你的synchronized作用范围只是给name赋值这一个操作而已

name赋值之后, 就是什么还是什么了

   你这真冷清。 你的帖子也挺木意思的

这下应该可以了...
就是记录学习的,本来就没什么意思。没事自己看看而已
1 楼 s929498110 2011-04-09  
 

第二个方法行吗?

你的synchronized作用范围只是给name赋值这一个操作而已

name赋值之后, 就是什么还是什么了

   你这真冷清。 你的帖子也挺木意思的

相关推荐

    servlet与Struts action线程安全问题分析

    线程安全是指在多线程环境中,一个类或者方法能够正确处理多个线程的并发访问,保证数据的一致性和完整性。 Servlet的多线程机制源于其生命周期的管理。当Web容器接收到客户端的首次请求时,会根据web.xml配置文件...

    1工作临时-servlet 多线程问题

    至于提供的文件"8点25分平安大厦集合旅游人员名单.xls",虽然与Servlet多线程问题无关,但可能是某个实际应用场景中涉及的数据或计划,比如用于统计并发访问的用户信息,或者是记录多线程处理过程中的某些状态信息。...

    Web-Servlet_多线程_

    当多个用户同时访问一个Servlet时,服务器通常会为每个请求创建一个新的线程来执行Servlet实例的方法,以实现并发处理。这使得Servlet天然支持多线程模型,能够处理大量并发请求,提高系统性能。 二、多线程在...

    深入研究Servlet线程安全性问题

    当两个或更多用户并发访问时,可能会出现线程A获取并设置`output`,然后线程B紧接着使用尚未被线程A完全处理的`output`,导致数据混乱。在并发测试中,通过人为引入延时,更容易暴露这个问题:用户a和b的请求可能会...

    应用sevlet和线程同步实现定时

    下面将详细探讨如何利用Servlet和线程同步来实现定时功能,以及与消息队列代码的相关性。 首先,让我们理解Servlet的工作原理。Servlet是Java类,它们由Web服务器加载并用于响应HTTP请求。Servlet生命周期包括加载...

    servlet与Struts action线程安全问题分析(pdf)

    #### 三、Servlet线程安全问题 线程安全问题主要发生在Servlet中使用实例变量时。当多个线程并发访问同一个Servlet实例时,如果这些线程试图同时修改实例变量,就可能发生数据不一致的情况。以下通过一个具体的示例...

    深入研究Servlet线程安全性问题.pdf

    ### 深入研究Servlet线程安全性问题 #### 一、引言 Servlet技术作为Java Web开发中的核心组件之一,因其高效性和灵活性被广泛应用于Web应用程序的开发中。Servlet能够处理HTTP请求,并产生相应的响应。它的一个...

    servlet是如何同时处理多个请求的

    由于多个线程可能同时访问同一实例,因此必须确保Servlet代码是线程安全的。如果Servlet内部有共享状态(如成员变量),需要采取同步机制,如`synchronized`关键字或使用线程局部变量来避免数据竞争。 2. **Servlet...

    使用synchronized实现多线程同步.pdf

    在Java编程中,多线程同步是一个至关重要的概念,它确保了多个线程在访问共享资源时能够有序进行,防止数据不一致性和竞态条件。`synchronized`关键字是Java中实现线程同步的主要手段之一。这篇文档主要讨论了如何...

    Java多线程

    - Java提供了一系列同步工具,如synchronized关键字、wait/notify机制、java.util.concurrent包中的并发工具类等,来确保线程间的同步与协调。 4. 线程安全与同步 - 线程安全指的是当多个线程访问一个对象时,...

    Springboot Druid多数据源 多线程

    总结起来,这个项目展示了如何利用Spring Boot和Druid实现多数据源切换,以及如何在Spring Boot中配置和使用多线程来提升数据库操作的并发性能。对于初学者,这是一个很好的学习资源,可以深入理解Spring Boot的自动...

    Java并发编程面试题

    * 在监视器(Monitor)内部,是如何做线程同步的? 线程池和Executor框架 * 什么是线程池? * Executor框架是什么? * 如何使用线程池和Executor框架? 线程安全 * 什么叫线程安全? * servlet是线程安全吗? * 在...

    Java面试题线程部分.docx

    实现线程同步的方法包括临界区、互斥对象、信号量、事件对象,以及Java中的同步方法、同步代码块、`volatile`关键字、`Lock`接口、`ThreadLocal`和阻塞队列等。 `run`和`start`方法是线程启动的关键。`run`方法只是...

    WEB多线程开发

    Servlet的多线程模型允许它同时处理多个客户端请求,提高了Web应用的并发处理能力。在编写Servlet时,开发者需要注意线程安全问题,确保共享资源的正确访问。 3. **Struts**:Struts是一个基于MVC(Model-View-...

    多线程的使用

    5. **线程同步与通信** - **同步**:为了避免线程间的竞态条件和死锁,Java提供了synchronized关键字、Lock接口(如ReentrantLock)等同步机制,确保同一时刻只有一个线程访问共享资源。 - **通信**:线程间通信...

Global site tag (gtag.js) - Google Analytics