大雀软件园

首页 软件下载 安卓市场 苹果市场 电脑游戏 安卓游戏 文章资讯 驱动下载
技术开发 网页设计 图形图象 数据库 网络媒体 网络安全 站长CLUB 操作系统 媒体动画 安卓相关
当前位置: 首页 -> 技术开发 -> JSP专区 -> Servlet及JSP中的多线程同步问题

Servlet及JSP中的多线程同步问题

时间: 2021-07-31 作者:daque

  servlet/jsp本领和asp、php等比拟,因为其多线程运转而具备很高的实行功效。因为servlet/jsp默许是以多线程形式实行的,以是,在编写代码时须要特殊精致地商量多线程的同步题目。但是,很多人编写servlet/jsp步调时并没有提防到多线程同步的题目,这常常形成编写的步调在小批用户考察时没有任何题目,而在并发用户飞腾到确定值时,就会常常展示少许莫名其妙的题目,对于这类随机性的题目调节和测试难度也很大。   一、在servlet/jsp中的几种变量典型   在编写servlet/jsp步调时,对范例变量确定要提防运用。由于范例变量利害线程安定的。在servlet/jsp中,变量不妨归为底下的几类:   1. 类变量   request,response,session,config,application,以及jsp页面内置的page, pagecontext。个中除去application外,其它都是线程安定的。   2. 范例变量   范例变量是范例一切的,在堆中调配。在servlet/jsp容器中,普遍仅范例化一个servlet/jsp范例,启用多个该范例的线程来处置乞求。而范例变量是该范例一切的线程所共享,以是,范例变量不是线程安定的。   3. 限制变量   限制变量在仓库中调配,由于每一个线程有本人的实行仓库,以是,限制变量是线程安定的。   二、在servlet/jsp中的多线程同步题目   在jsp中,运用范例变量要更加精心。开始请看底下的代码: // instanceconcurrenttest.jsp<%@ page contenttype="text/html;charset=gbk" %><%! //设置范例变量 string username; string password; java.io.printwriter output;%><% //从request中获得参数 username = request.getparameter("username"); password = request.getparameter("password"); output = response.getwriter(); showuserinfo(); %> <%! public void showuserinfo() { //为了超过并发题目,在这边开始实行一个费时操纵 int i =0; double sum = 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两个线程的输入。请看底下的屏幕截图:

servlet及jsp中的多线程同步问题图1

图1:a的屏幕

servlet及jsp中的多线程同步问题图2

图2: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的代替。请加入下图所示:

servlet及jsp中的多线程同步问题图3

图3:a、b两个线程的功夫线

  而本质步调中,因为树立范例变量,运用范例变量这两个功夫点特殊逼近,以是,像本例的同步题目并没有这么超过,大概会偶然展示,但这却越发具备伤害性,也越发难于调节和测试。   同样,对于servlet也生存范例变量的多线程题目,请看上头页面包车型的士servlet版: // instanceconcurrenttest.javaimport javax.servlet.*;import javax.servlet.http.*;import java.io.printwriter;public class instanceconcurrenttest extends httpservlet { string username; string password; printwriter out; public void doget(httpservletrequest request, httpservletresponse response) throws servletexception,java.io.ioexception { //从request中获得参数 username = request.getparameter("username"); password = request.getparameter("password"); system.out.println(thread.currentthread().getname() + " | set username:" + username); out = response.getwriter(); showuserinfo(); } public void showuserinfo() { //为了超过并发题目,在这边开始实行一个费时操纵 int i =0; double sum = 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中,经过树立:<%@ page isthreadsafe="false" %>,在servlet中,经过实行javax.servlet.singlethreadmodel,此时web容器将保护jsp或servlet范例以单线程办法运转。   要害提醒:在尝试中创造,tomcat 4.1.17不许精确扶助isthreadsafe属性,以是,指定istheadsafe为false后,在tomcat 4.1.17中仍旧展示多线程题目,这是tomcat 4.1.17的bug。在tomcat 3.3.1和resin 2.1.第5中学尝试经过。   2. 去除范例变量,经过参数传播   从上头的领会看来,该当在servlet/jsp中尽管制止运用范例变量。比方,底下的矫正代码,去除去范例变量,经过设置限制变量,并参数举行传播。如许,因为限制变量是在线程的仓库中举行调配的,以是是线程安定的。不会展示多线程同步的题目。代码如次: <%@ page contenttype="text/html;charset=gbk" %><% //运用限制变量 string username; string password; java.io.printwriter output; //从request中获得参数 username = request.getparameter("username"); password = request.getparameter("password"); output = response.getwriter(); showuserinfo(output, username, password);%><%! public void showuserinfo(java.io.printwriter _output, string _username, string _password) { //为了超过并发题目,在这边开始实行一个费时操纵 int i =0; double sum = 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要害字举行同步,但如许并不许处置多线程的题目。由于,如许固然不妨使对范例变量的操纵代码举行同步,但并不许遏止一个线程运用其余一个线程窜改后的“脏的”范例变量。以是,除去贬低运转功效外,不会起到预期功效。

热门阅览

最新排行

Copyright © 2019-2021 大雀软件园(www.daque.cn) All Rights Reserved.