设为首页收藏本站language 语言切换
查看: 2948|回复: 1
收起左侧

在Servlet和JSP中如何实现多线程安全?

[复制链接]
发表于 2010-2-20 15:06:50 | 显示全部楼层 |阅读模式
<p >1.Servlet的生命周期<p >Servlet的生命周期是由Web容器负责的,当客户端第一次请求Servlet时,容器负责初始化Servlet,也就是实例化这个Servlet类.以后这个实例就负责客户端的请求,一般不会再实例化其他Servlet类,也就是有多个线程在使用这个实例.Servlet之所以比CGI效率高就是因为Servlet是多线程的.如果该Servlet被声明为单线程模型的话,容器就会维护一个实例池,那么将存在多个实例.<p >2.Servlet的线程安全<p >Servlet规范已经声明Servlet不是线程安全的,所以在开发Servlet的时候要注要这个问题.这里以一个现实的模型来说明问题,先定义一个Servlet类,再定义一个SmulateMultiThread类和WebContainer类.<p ><CENTER><ccid_nobr><table width="400" border="1" cellspacing="0" cellpadding="2"  bordercolorlight = "black" bordercolordark = "#FFFFFF" align="center"><tr><td bgcolor="e6e6e6" class="code" ><pre><ccid_code>import javax.servlet.http.HttpServlet;import javax.servlet.ServletException;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;//该类模拟多线程Servlet的情况public class SmulateMultiThread implements Runnable{  public SmulateMultiThread() {  }  public static void main(String[] args) {   //处理100个请求    for(int i=0;i&lt;100;i++)    {      new Thread(new SmulateMultiThread()).start();    }  }  public void run()  {    HttpServletRequest request=null;    HttpServletResponse  response=null;    try {      WebContainer.getServlet().doGet(request, response);    }    catch (IOException ex) {    }    catch (ServletException ex) {    }  }}//这是一个Servlet类class UnsafeServlet extends HttpServlet{  private String unsafe;  public void init() throws ServletException {  }  //Process the HTTP Get request  public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {    unsafe=Thread.currentThread().getName();    System.out.println(unsafe);  }}//这个是容器类class WebContainer{  private static UnsafeServlet us=new UnsafeServlet();  public static UnsafeServlet getServlet(){    return us;  }}</ccid_code></pre></td></tr></table></ccid_nobr></CENTER><p >输出了100不同的线程名称,如果有100个请求同时被这个Servlet处理的话,那么unsafe就可能有100种去值,最后客户端将得到错误的值.比如客户1请求的线程名为thread-1,但是返回给他的可能是thread-20.表现在现实中就是,我登陆的用户名是user1,登陆后变成了user2.<p >那么怎样才能是Servlet安全呢,凡是多个线程可以共享的就不要使用(实例变量+类变量),就这么简单.也可以使用synchronized同步方法,但是这样效率不高,还可以使用单线程模型,这样的话效率就更低了,100个请求同时来的时候就要实例化100个实例.<p >方法中的临时变量是不会影响线程安全的,因为他们是在栈上分配空间,而且每个线程都有自己私有的栈空间.<p >3.JSP中线程安全<p >JSP的本质是Servlet,所有只要明白了Servlet的安全问题,JSP的安全问题应该很容易理解.使用<%! %>声明的变量是Servlet的实例变量,不是线程安全的,其他都是线程安全的.<p ><CENTER><ccid_nobr><table width="400" border="1" cellspacing="0" cellpadding="2"  bordercolorlight = "black" bordercolordark = "#FFFFFF" align="center"><tr><td bgcolor="e6e6e6" class="code" ><pre><ccid_code>&lt;%! String unsafeVar; %&gt; //不是线程安全的&lt;% String safeVar; %&gt;      // 线程安全的</ccid_code></pre></td></tr></table></ccid_nobr></CENTER><p >总结:线程安全问题主要是由实例变量造成的,不管在Servlet还是JSP,或者在Struts的Action里面,不要使用实例变量,任何方法里面都不要出现实例变量,你的程序就是线程安全的.<p >(责任编辑:董建伟)                                 <p align="center"></p></p>
发表于 2010-3-18 11:47:58 | 显示全部楼层
沙发 2010-3-18 11:47:58 回复 收起回复
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 论坛注册

本版积分规则

QQ|Archiver|手机版|小黑屋|sitemap|鸿鹄论坛 ( 京ICP备14027439号 )  

GMT+8, 2025-4-8 16:38 , Processed in 0.086703 second(s), 23 queries , Redis On.  

  Powered by Discuz!

  © 2001-2025 HH010.COM

快速回复 返回顶部 返回列表