|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
你对java乐观有点盲目。java的关键就是在服务器上表现优异,而且它提供了整个开发所需要的工具。应该是说,看哪天。net有没有机会赶上java。js|servlet|多线程|成绩
Servlet/JSP手艺和ASP、PHP等比拟,因为其多线程运转而具有很高的实行效力。因为Servlet/JSP默许是以多线程形式实行的,以是,在编写代码时必要十分仔细地思索多线程的同步成绩。但是,良多人编写Servlet/JSP程序时并没有注重到多线程同步的成绩,这常常形成编写的程序在大批用户会见时没有任何成绩,而在并发用户上升到必定值时,就会常常呈现一些莫明其妙的成绩,关于这类随机性的成绩调试难度也很年夜。
1、在Servlet/JSP中的几种变量范例
在编写Servlet/JSP程序时,对实例变量必定要当心利用。由于实例变量长短线程平安的。在Servlet/JSP中,变量能够回为上面的几类:
1.类变量
request,response,session,config,application,和JSP页面内置的page,pageContext。个中除application外,别的都是线程平安的。
2.实例变量
实例变量是实例一切的,在堆平分配。在Servlet/JSP容器中,一样平常仅实例化一个Servlet/JSP实例,启动多个该实例的线程来处置哀求。而实例变量是该实例一切的线程所共享,以是,实例变量不是线程平安的。
3.部分变量
部分变量在仓库平分配,由于每个线程有本人的实行仓库,以是,部分变量是线程平安的。
2、在Servlet/JSP中的多线程同步成绩
在JSP中,利用实例变量要出格审慎。起首请看上面的代码:
ffffffcellPadding=2width=540align=centerborderColorLight=blackborder=1>- //instanceconcurrenttest.jsp<%@pagecontentType="text/html;charset=GBK"%><%!//界说实例变量Stringusername;Stringpassword;java.io.PrintWriteroutput;%><%//从request中猎取参数username=request.getParameter("username");password=request.getParameter("password");output=response.getWriter();showUserInfo();%><%!publicvoidshowUserInfo(){//为了凸起并提问题,在这儿起首实行一个费时操纵inti=0;doublesum=0.0;while(i++<200000000){sum+=i;}output.println(Thread.currentThread().getName()+"<br>");output.println("username:"+username+"<br>");output.println("password:"+password+"<br>");}%>
复制代码
在这个页面中,起首界说了两个实例变量,username和password。然后在从request中猎取这两个参数,并挪用showUserInfo()办法将哀求用户的信息回显在该客户的扫瞄器上。在一个用户会见是,不存在成绩。但在多个用户并发会见时,就会呈现别的用户的信息显现在别的一些用户的扫瞄器上的成绩。这是一个严峻的成绩。为了凸起并提问题,便于测试、察看,我们在回显用户信息时实行了一个摹拟的费时操纵,好比,上面的两个用户同时会见(能够启动两个IE扫瞄器,大概在两台呆板上同时会见):
a:http://localhost:8080/instanceconcurrenttest.jsp?username=a&password=123
b:http://localhost:8080/instanceconcurrenttest.jsp?username=b&password=456
假如a点击链接后,b再点击链接,那末,a将前往一个空缺屏幕,b则失掉a和b两个线程的输入。请看上面的屏幕截图:
<br>
:a的屏幕
<br>
:b的屏幕
从运转了局的截图上能够看到,Web服务器启动了两个线程分离来处置来自a和b的哀求,可是在a却失掉一个空缺的屏幕。这是由于下面程序中的output,username和password都是实例变量,是一切线程共享的。在a会见该页面后,将output设置为a的输入,username,password分离置为a的信息,而在a实行printUserInfo()输入username和password信息前,b又会见了该页面,把username和password置为了b的信息,并把输入output指向到了b。随后a的线程打印时,就打印到了b的屏幕了,而且,a的用户名和暗码也被b的代替。请列入下图所示:
<br>
:a、b两个线程的工夫线
而实践程序中,因为设置实例变量,利用实例变量这两个工夫点十分靠近,以是,像本例的同步成绩并没有这么凸起,大概会偶然呈现,但这却加倍具有伤害性,也加倍难于调试。
一样,关于Servlet也存在实例变量的多线程成绩,请看下面页面的Servlet版:
- //InstanceConcurrentTest.javaimportjavax.servlet.*;importjavax.servlet.http.*;importjava.io.PrintWriter;publicclassInstanceConcurrentTestextendsHttpServlet{Stringusername;Stringpassword;PrintWriterout;publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,java.io.IOException{//从request中猎取参数username=request.getParameter("username");password=request.getParameter("password");System.out.println(Thread.currentThread().getName()+"|setusername:"+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);}}
复制代码
3、办理计划
1.以单线程运转Servlet/JSP
在JSP中,经由过程设置:<%@pageisThreadSafe="false"%>,在Servlet中,经由过程完成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中只管制止利用实例变量。好比,上面的修改代码,往除实例变量,经由过程界说部分变量,并参数举行传送。如许,因为部分变量是在线程的仓库中举行分派的,以是是线程平安的。不会呈现多线程同步的成绩。代码以下:
- <%@pagecontentType="text/html;charset=GBK"%><%//利用部分变量Stringusername;Stringpassword;java.io.PrintWriteroutput;//从request中猎取参数username=request.getParameter("username");password=request.getParameter("password");output=response.getWriter();showUserInfo(output,username,password);%><%!publicvoidshowUserInfo(java.io.PrintWriter_output,String_username,String_password){//为了凸起并提问题,在这儿起首实行一个费时操纵inti=0;doublesum=0.0;while(i++<200000000){sum+=i;}_output.println(Thread.currentThread().getName()+"<br>");_output.println("username:"+_username+"<br>");_output.println("password:"+_password+"<br>");}%>
复制代码
注:有的材料上指出在printUserInfo()办法大概实例变量的相干操纵语句上利用synchronized关头字举行同步,但如许其实不能办理多线程的成绩。由于,如许固然可使对实例变量的操纵代码举行同步,但其实不能制止一个线程利用别的一个线程修正后的“脏的”实例变量。以是,除下降运转效力外,不会起到预期效果。
由于这些智能化家电的市场需求没有预期的高,Sun放弃了该项计划。就在Oak几近失败之时,随着互联网的发展,Sun看到了Oak在计算机网络上的广阔应用前景,于是改造了Oak, |
|