Servlet及JSP中的多线程同步问题_第1页
Servlet及JSP中的多线程同步问题_第2页
Servlet及JSP中的多线程同步问题_第3页
Servlet及JSP中的多线程同步问题_第4页
Servlet及JSP中的多线程同步问题_第5页
已阅读5页,还剩1页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、Servlet及JSP中的多线程同步问题Servlet/JSP技术和ASP、PHP等相比,由于其多线程运行而具有很高的执行效率。由于Servlet/JSP默认是以多线程模式执行的,所以,在编写代码时需要非常细致地考虑多线程的同步问题。然而,很多人编写Servlet/JSP程序时并没有注意到多线程同步的问题,这往往造成编写的程序在少量用户访问时没有任何问题,而在并发用户上升到一定值时,就会经常出现一些莫明其妙的问题,对于这类随机性的问题调试难度也很大。一、在Servlet/JSP中的几种变量类型在编写Servlet/JSP程序时,对实例变量一定要小心使用。因为实例变量是非线程安全的。在Servl

2、et/JSP中,变量可以归为下面的几类:1.类变量request,response,session,config,application,以及JSP页面内置的page,pageContext。其中除了application外,其它都是线程安全的。2.实例变量实例变量是实例所有的,在堆中分配。在Servlet/JSP容器中,一般仅实例化一个Servlet/JSP实例,启动多个该实例的线程来处理请求。而实例变量是该实例所有的线程所共享,所以,实例变量不是线程安全的。3.局部变量局部变量在堆栈中分配,因为每一个线程有自己的执行堆栈,所以,局部变量是线程安全的。二、在Servlet/JSP中的多线程同

3、步问题在JSP中,使用实/例变量要特别谨慎。首先请看下面的代码:instanceconcurrenttest.jsp%!publicvoidshowUserInfo()/为了突出并发问题,在这儿首先执行一个费时操作inti=0;doublesum=0.0;while(i+在这个页面中,首先定义了两个实例变量,username和password。然后在从request中获取这两个参数,并调用showUserInfo()方法将请求用户的信息回显在该客户的浏览器上。在一个用户访问是,不存在问题。但在多个用户并发访问时,就会出现其它用户的信息显示在另外一些用户的浏览器上的问题。这是一个严重的问题。为了

4、突出并发问题,便于测试、观察,我们在回显用户信息时执行了一个模拟的费时操作,比如,下面的两个用户同时访问(可以启动两个IE浏览器,或者在两台机器上同时访问):a:http:/localhost:8080/instanceconcurrenttest.jsp?username=a&password=123b:http:/localhost:8080/instanceconcurrenttest.jsp?username=b&password=456如果a点击链接后,b再点击链接,那么,a将返回一个空白屏幕,b则得到a以及b两个线程的输出。请看下面的屏幕截图:图1:a的屏幕图2:b的屏幕从运行结果

5、的截图上可以看到,Web服务器启动了两个线程分别来处理来自a和b的请求,但是在a却得到一个空白的屏幕。这是因为上面程序中的output,username和password都是实例变量,是所有线程共享的。在a访问该页面后,将output设置为a的输由,username,password分另I置为a的信息、,而在a执行printUserInfo()输由username和password信息前,b又访问了该页面,把username和password置为了b的信息、,并把输由output指向到了bo随后a的线程打印时,就打印到了b的屏幕了,并且,a的用户名和密码也被b的取代。请参加下图所示:图3:a、

6、b两个线程的时间线而实际程序中,由于设置实例变量,使用实例变量这两个时间点非常接近,所以,像本例的同步问题并没有这么突出,可能会偶尔出现,但这却更加具有危险性,也更加难于调试。同样,对于Servlet也存在实例变量的多线程问题,请看上面页面的Servlet版:/InstanceConcurrentTest.javaimportjavax.servlet.*;importjavax.servlet.http.*;importjava.io.PrintWriter;publicclassInstanceConcurrentTestextendsHttpServletStringusername;S

7、tringpassword;PrintWriterout;publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,java.io.IOException/从request中获取参数username=request.getParameter(username);password=request.getParameter(password);System.out.println(Thread.currentThread().getName()+|setusername:

8、+username);out=response.getWriter();showUserInfo();publicvoidshowUserInfo()/为了突出并发问题,在这儿首先执行一个费时操作inti=0;doublesum=0.0;while(i+200000000)sum+=i;out.println(thread:+Thread.currentThread().getName();out.println(username:+username);out.println(password:+password);三、解决方案1.以单线程运行Servlet/JSP在JSP中,通过设置:,在S

9、ervlet中,通过实现javax.servlet.SingleThreadModel,此时Web容器将保证JSP或Servlet实例以单线程方式运行。重要提示:在测试中发现,Tomcat4.1.17不能正确支持isThreadSafe属性,所以,指定isTheadSafe为false后,在Tomcat4.1.17中仍然出现多线程问题,这是Tomcat4.1.17的Bug。在Tomcat3.3.1和Resin2.1.5中测试通过。2.去除实例变量,通过参数传递从上面的分析可见,应该在Servlet/JSP中尽量避免使用实例变量。比如,下面的修正代码,去除了实例变量,通过定义局部变量,并参数进行传递。这样,由于局部变量是在线程的堆栈中进行分配的,所以是线程安全的。不会出现多线程同步的问题。代码如下:%!publicvoidshowUserInfo(java.io.PrintWriter_output,String_username,String_password)/为了突出并发问题,在这儿首先执行一个费时操作inti=0;doublesum=0.0;while(i+注:有的

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论