servlet注意事项

    不同的用户同时对同一个业务url发出请求,这个时候容器里产生只有一个servlet对象,即单例模式,也就是说

不管你在地球的那个地方只要访问的是同一个url,那就是访问同一个对象。当同时10个人访问一个对象,

同时调用这个servlet对象方法service(),就会有线程同步问题。

Servlet是如何处理多个请求同时访问呢?

Servlet容器默认是采用单实例多线程的方式处理多个请求的:

1.      当web服务器启动的时候(或客户端发送请求到服务器时),Servlet就被加载并实例化(只存在一个Servlet实例);

2.      容器初始化Servlet。主要就是读取配置文件(例如tomcat,可以通过servlet.xml的<Connector>设置线程池中线程数目,初始化线程池;通过web.xml,初始化每个参数值等等);

3.      当请求到达时,Servlet容器通过调度线程(Dispatchaer Thread)调度它管理下的线程池中等待执行的线程(Worker Thread)给请求者;

4.      线程执行Servlet的service方法;

5.      请求结束,放回线程池,等到被调用;

从上面可以看出:
第一:Servlet单实例,减少了产生servlet的开销;

第二:通过线程池来响应多个请求,提高了请求的响应时间;

第三:Servlet容器并不关心到达的Servlet请求访问的是否是同一个Servlet还是另一个Servlet,直接分配给它一个新的线程;如果是同一个Servlet的多个请求,那么Servlet的service方法将在多线程中并发的执行;

第四:每一个请求由ServletRequest对象来接受请求,由ServletResponse对象来响应该请求;

问题出现了:
同一个Servlet的的多个请求到来时,如果该Servlet中存在成员变量,可能发生多线程同时访问该资源时,都来操作它,造成数据的不一致,因此产生线程安全问题。

解决:

1.      实现SingleThreadModel接口

如果一个Servlet被这个接口指定,那么在这个Servlet中的service方法将不会有两个线程被同时执行,当然也就不存在线程安全的问题;


2.      同步对共享数据的操作

使用synchronized关键字能保证一次只有一个线程可以访问被保护的区段,Servlet可以通过同步块操作来保证线程的安全。
ServletRequest对象是线程安全的,但是ServletContext和HttpSession不是线程安全的;
要使用同步的集合类:Vector代替ArrayList,HsahTable代替HashMap;


3.      避免使用实例变量(成员变量)


线程安全问题是由实例变量造成的,只要在Servlet里面的任何方法里面都不使用实例变量,那么该Servlet就是线程安全的。(所有建议不要在servlet中定义成员变量,尽量用局部变量代替)

对上面的三种方法进行测试,可以表明用它们都能设计出线程安全的Servlet程序。但是,如果一个Servlet实现了SingleThreadModel接口,Servlet引擎将为每个新的请求创建一个单独的Servlet实例,这将引起大量的系统开销。SingleThreadModel在Servlet2.4中已不再提倡使用;同样如果在程序中使用同步来保护要使用的共享的数据,也会使系统的性能大大下降。这是因为被同步的代码块在同一时刻只能有一个线程执行它,使得其同时处理客户请求的吞吐量降低,而且很多客户处于阻塞状态。另外为保证主存内容和线程的工作内存中的数据的一致性,要频繁地刷新缓存,这也会大大地影响系统的性能。所以在实际的开发中也应避免或最小化Servlet中的同步代码;在Serlet中避免使用实例变量是保证Servlet线程安全的最佳选择。从Java内存模型也可以知道,方法中的临时变量是在栈上分配空间,而且每个线程都有自己私有的栈空间,所以它们不会影响线程的安全。


 Servlet的线程安全问题只有在大量的并发访问时才会显现出来,并且很难发现,因此在编写Servlet程序时要特别注意。线程安全问题主要是由实例变量造成的,因此在Servlet中应避免使用实例变量。如果应用程序设计无法避免使用实例变量,那么使用同步来保护要使用的实例变量,但为保证系统的最佳性能,应该同步可用性最小的代码路径。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值