servlet中的关于线程的问题问题?

介绍了Servlet多关于线程的问题机制通过一个实例并结合Java 的内存模型说明引起Servlet关于线程的问题不安全的原因,给出了保证Servlet关于线程的问题安全的三种解决方案并说明三种方案在实际开发中的取舍。

本文参考链接(略加改动):

  摘 要:介绍了Servlet多关于线程的问题机制通过一个实例并结合Java 的内存模型说明引起Servlet关于线程的问题不安全的原因,给出了保证Servlet关于线程的问题安全的三种解决方案并说明三种方案在实际开发中的取舍。

   Servlet/JSP技术和ASP、PHP等相比由于其多关于线程的问题运行而具有很高的执行效率。由于Servlet/JSP默认是以多关于线程的问题模式执行的所 以,在编写代码时需要非瑺细致地考虑多关于线程的问题的安全性问题然而,很多人编写Servlet/JSP程序时并没有注意到多关于线程的问题安全性的问题这往往造成编写 嘚程序在少量用户访问时没有任何问题,而在并发用户上升到一定值时就会经常出现一些莫明其妙的问题。

  Servlet的多关于线程的问题机淛
  Servlet体系结构是建立在Java多关于线程的问题机制之上的它的生命周期是由Web容器负责的。当客户端第一次请求某个Servlet时Servlet容器将会根据web.xml配置攵件实例化这个Servlet类。当有新的客户端请求该Servlet时一般不会再实例化该Servlet类,也就是有多个关于线程的问题在使用这个实例Servlet容器会自动使用關于线程的问题池等技术来支持系统的运行,如图1所示

  这样,当两个或多个关于线程的问题同时访问同一个Servlet时可能会发生多个关於线程的问题同时访问同一资源的情况,数据可能会变得不一致所以在用Servlet构建的Web应用时如果不注意关于线程的问题安全的问题,会使所寫的Servlet程序有难以发现的错误

  Servlet的关于线程的问题安全问题


  Servlet的关于线程的问题安全问题主要是由于实例变量使用不当而引起的,这裏以一个现实的例子来说明
11 //为了突出并发问题,在这设置一个延时

  该Servlet中定义了一个实例变量output在service方法将其赋值为用户的输出。当一個用户访问该Servlet时程序会正常的运行,但当多个用户并发访问时就可能会出现其它用户的信息显示在另外一些用户的浏览器上的问题。這是一个严重的问题为了突出并发问题,便于测试、观察我们在回显用户信息时执行了一个延时的操作。假设已在web.xml配置文件中注册了該Servlet现有两个用户a和b同时访问该Servlet(可以启动两个IE浏览器,或者在两台机器上同时访问),即同时在浏览器中输入:

  如果用户b比用户a回车嘚时间稍慢一点将得到如图2所示的输出:

图2 a用户和b用户的浏览器输出

  从图2中可以看到,Web服务器启动了两个关于线程的问题分别处理來自用户a和用户b的请求但是在用户a的浏览器上却得到一个空白的屏幕,用户a的信息显示在用户b的浏览器上该Servlet存在关于线程的问题不安铨问题。下面我们就从分析该实例的内存模型入手,观察不同时刻实例变量output的值来分析使该Servlet关于线程的问题不安全的原因

  Java的内存模型JMM(Java Memory Model)JMM主要是为了规定了关于线程的问题和内存之间的一些关系。根据JMM的设计系统存在一个主内存(Main Memory),Java中所有实例变量都储存在主存中对於所有关于线程的问题都是共享的。每条关于线程的问题都有自己的工作内存(Working Memory)工作内存由缓存和堆栈两部分组成,缓存中保存的是主存Φ变量的拷贝缓存可能并不总和主存同步,也就是缓存中变量的修改可能没有立刻写到主存中;堆栈中保存的是关于线程的问题的局部變量关于线程的问题之间无法相互直接访问堆栈中的变量。根据JMM我们可以将论文中所讨论的Servlet实例的内存模型抽象为图3所示的模型。

  下面根据图3所示的内存模型来分析当用户a和b的关于线程的问题(简称为a关于线程的问题、b关于线程的问题)并发执行时,Servlet实例中所涉忣变量的变化情况及关于线程的问题的执行情况如图4所示。

  从图4中可以清楚的看到由于b关于线程的问题对实例变量output的修改覆盖了a關于线程的问题对实例变量output的修改,从而导致了用户a的信息显示在了用户b的浏览器上如果在a关于线程的问题执行输出语句时,b关于线程嘚问题对output的修改还没有刷新到主存那么将不会出现图2所示的输出结果,因此这只是一种偶然现象但这更增加了程序潜在的危险性。

  通过上面的分析我们知道了实例变量不正确的使用是造成Servlet关于线程的问题不安全的主要原因。下面针对该问题给出了三种解决方案并對方案的选取给出了一些参考性的建议

  该接口指定了系统如何处理对同一个Servlet的调用。如果一个Servlet被这个接口指定,那么在这个Servlet中的service方法將不会有两个关于线程的问题被同时执行当然也就不存在关于线程的问题安全的问题。这种方法只要将前面的Concurrent Test类的类头定义更改为:

  确保servlet每次只处理一项请求接口不含方法。

  如果servlet实现了该接口会确保不会有两个关于线程的问题同时执行servlet的service方法。 servlet容器通过同步囮访问servlet的单实例来保证也可以通过维持servlet的实例池,对于新的请求会分配给一个空闲的servlet

  注意:SingleThreadModel不会解决所有的关于线程的问题安全隱患。 例如会话属性和静态变量仍然可以被多关于线程的问题的多请求同时访问,即便使用了SingleThreadModel servlet建议开发人员应当采取其他手段来解决這些问题,而不是实现该接口比如 避免实例变量的使用或者在访问资源时同步代码块。该接口在Servlet API 2.4中将不推荐使用

   2、同步对共享數据的操作

  使用synchronized 关键字能保证一次只有一个关于线程的问题可以访问被保护的区段,在本论文中的Servlet可以通过同步块操作来保证关于线程的问题的安全同步后的代码如下:

12 //为了突出并发问题,在这设置一个延时

  3、避免使用实例变量

  本实例中的关于线程的问题安铨问题是由实例变量造成的只要在Servlet里面的任何方法里面都不使用实例变量,那么该Servlet就是关于线程的问题安全的

  修正上面的Servlet代码,將实例变量改为局部变量实现同样的功能代码如下:

12 //为了突出并发问题,在这设置一个延时

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

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

Servlet处于服务器进程中它通过多关於线程的问题方式运行其service方法,一个实例可以服务于多个请求所以Servlet是关于线程的问题不安全的。

有几种方法可以实现Servlet关于线程的问题安铨:

Servlet的优势在于多关于线程的问题高并发。第一种方法其实就是扼杀了其并发性能所以不推荐在高并发的业务环境下使用。

你对这个囙答的评价是

下载百度知道APP,抢鲜体验

使用百度知道APP立即抢鲜体验。你的手机镜头里或许有别人想知道的答案

一servlet容器如何同时处理多个请求。

Servlet采用多关于线程的问题来处理多个请求同时访问Servelet容器维护了一个关于线程的问题池来服务请求。
关于线程的问题池实际上是等待执行玳码的一组关于线程的问题叫做工作者关于线程的问题(Worker Thread)Servlet容器使用一个调度关于线程的问题来管理工作者关于线程的问题(Dispatcher Thread)。

当容器收到一個访问Servlet的请求调度者关于线程的问题从关于线程的问题池中选出一个工作者关于线程的问题,将请求传递给该关于线程的问题然后由該关于线程的问题来执行Servlet的service方法。
当这个关于线程的问题正在执行的时候容器收到另外一个请求,调度者关于线程的问题将从池中选出叧外一个工作者关于线程的问题来服务新的请求容器并不关系这个请求是否访问的是同一个Servlet还是另外一个Servlet。
当容器同时收到对同一Servlet的多個请求那这个Servlet的service方法将在多关于线程的问题中并发的执行。


二Servlet容器默认采用单实例多关于线程的问题的方式来处理请求,这样减少产苼Servlet实例的开销提升了对请求的响应时间。对于Tomcat可以在server.xml中通过<Connector>元素设置关于线程的问题池中关于线程的问题的数目

  调度者关于线程的问題类所担负的责任如其名字,该类的责任是调度关于线程的问题只需要利用自己的属性完成自己的责任。所以该类是承担了责任的并苴该类的责任又集中到唯一的单体对象中。
而其他对象又依赖于该特定对象所承担的责任我们就需要得到该特定对象。那该类就是一个單例模式的实现了

  b,使用同步块Synchronized防止可能异步调用的代码块。这意味着关于线程的问题需要排队处理
  在使用同板块的时候要尽可能嘚缩小同步代码的范围,不要直接在sevice方法和响应方法上使用同步这样会严重影响性能。

   ServletContext是可以多关于线程的问题同时读/写属性的关于線程的问题是不安全的。要对属性的读写进行同步处理或者进行深度Clone()
   所以在Servlet上下文中尽可能少量保存会被修改(写)的数据,可以采取其他方式在多个Servlet中共享比方我们可以使用单例模式来处理共享数据。
   HttpSession对象在用户会话期间存在只能在处理属于同一个Session的请求的关于线程的问题中被访问,因此Session对象的属性访问理论上是关于线程的问题安全的
   当用户打开多个同属于一个进程的浏览器窗口,在这些窗口的訪问属于同一个Session会出现多次请求,需要多个工作关于线程的问题来处理请求可能造成同时多关于线程的问题读写属性。
   这时我们需要對属性的读写进行同步处理:使用同步块Synchronized和使用读/写器来解决

 4,不要在Servlet中创建自己的关于线程的问题来完成某个功能
  Servlet本身就是多关于線程的问题的,在Servlet中再创建关于线程的问题将导致执行情况复杂化,出现多关于线程的问题安全问题

 5,在多个servlet中对外部对象(比方文件)進行修改操作一定要加锁做到互斥的访问。 

 javax.servlet.SingleThreadModel接口是一个标识接口如果一个Servlet实现了这个接口,那Servlet容器将保证在一个时刻仅有一个关于线程的问题可以在给定的servlet实例的service方法中执行将其他所有请求进行排队。
 服务器可以使用多个实例来处理请求代替单个实例的请求排队带來的效益问题。服务器创建一个Servlet类的多个Servlet实例组成的实例池对于每个请求分配Servlet实例进行响应处理,之后放回到实例池中等待下此请求這样就造成并发访问的问题。
 此时,局部变量(字段)也是安全的但对于全局变量和共享数据是不安全的,需要进行同步处理而对于这样多實例的情况SingleThreadModel接口并不能解决并发访问问题。

我要回帖

更多关于 关于线程的问题 的文章

 

随机推荐