`
androidssh
  • 浏览: 112807 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

Servlet和JSP的线程安全问题

阅读更多
   编写Servlet和JSP的时候,线程安全问题很容易被忽略,如果忽视了这个问题,你的程序就存在潜在的隐患.
一、Servlet的线程安全简介
1、Servlet的生命周期
    Servlet的生命周期是由Web容器负责的,当客户端第一次请求Servlet时,容器负责初始化Servlet,也就是实例化这个Servlet类.以后这个实例就负责客户端的请求,一般不会再实例化其他Servlet类,也就是有多个线程在使用这个实例.Servlet之所以比CGI效率高就是因为Servlet是多线程的.如果该Servlet被声明为单线程模型的话,容器就会维护一个实例池,那么将存在多个实例.
2、Java的内存模型JMM(Java Memory Model)
    JMM主要是为了规定了线程和内存之间的一些关系。根据JMM的设计,系统存在一个主内存(Main Memory),Java中所有实例变量都储存在主存中,对于所有线程都是共享的。每条线程都有自己的工作内存(Working Memory),工作内存由缓存和堆栈两部分组成,缓存中保存的是主存中变量的拷贝,缓存可能并不总和主存同步,也就是缓存中变量的修改可能没有立刻写到主存中;堆栈中保存的是线程的局部变量(save in stack, not in heap),线程之间无法相互直接访问堆栈中的变量.

3、Servlet的线程安全
    Servlet规范已经声明Servlet不是线程安全的,所以在开发Servlet的时候要注要这个问题.这里以一个现实的模型来说明问题,先定义一个Servlet类,再定义一个SmulateMultiThread类和WebContainer类.
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<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;
  }
}
    输出了100不同的线程名称,如果有100个请求同时被这个Servlet处理的话,那么unsafe就可能有100种去值,最后客户端将得到错误的值.比如客户1请求的线程名为thread-1,但是返回给他的可能是thread-20.表现在现实中就是,我登陆的用户名是user1,登陆后变成了user2.
    那么怎样才能是Servlet安全呢,凡是多个线程可以共享的就不要使用(实例变量+类变量),就这么简单.也可以使用synchronized同步方法,但是这样效率不高,还可以使用单线程模型,这样的话效率就更低了,100个请求同时来的时候就要实例化100个实例.
方法中的临时变量是不会影响线程安全的,因为他们是在栈上分配空间,而且每个线程都有自己私有的栈空间.

二、Servelt安全线程设计方法
    通过上面的分析,我们知道了实例变量不正确的使用是造成Servlet线程不安全的主要原因。下面针对该问题给出了三种解决方案并对方案的选取给出了一些参考性的建议。
1、实现 SingleThreadModel 接口
  该接口指定了系统如何处理对同一个Servlet的调用。如果一个Servlet被这个接口指定,那么在这个Servlet中的service方法将不会有两个线程被同时执行,当然也就不存在线程安全的问题。这种方法只要将前面的UnsafeServlet类的类头定义更改为:
public class UnsafeServlet  extends HttpServlet implements SingleThreadModel {
…………
}
2、同步对共享数据的操作
  使用synchronized 关键字能保证一次只有一个线程可以访问被保护的区段,在本论文中的Servlet可以通过同步块操作来保证线程的安全。同步后的代码如下:
…………
Public class UnsafeServlet  extends HttpServlet {
     …………
username = request.getParameter ("username");
synchronized (this){
output = response.getWriter ();
try {
     Thread. Sleep (5000);
} Catch (Interrupted Exception e){}
     output.println("用户名:"+Username+"
");
    }
  }
}
3、避免使用实例变量
  本实例中的线程安全问题是由实例变量造成的,只要在Servlet里面的任何方法里面都不使用实例变量,那么该Servlet就是线程安全的。
  修正上面的Servlet代码,将实例变量改为局部变量实现同样的功能,代码如下:
……
public class UnsafeServlet   extends HttpServlet {
     public void service (HttpServletRequest request,
             HttpServletResponse response) throws ServletException, IOException {
         PrintWriter output;
         String username;
         response.setContentType ("text/html; charset=gb2312");
         ……
     }
}
  对上面的三种方法进行测试,可以表明用它们都能设计出线程安全的Servlet程序。但是,如果一个Servlet实现了 SingleThreadModel接口,Servlet引擎将为每个新的请求创建一个单独的Servlet实例,这将引起大量的系统开销。 SingleThreadModel在Servlet2.4中已不再提倡使用;同样如果在程序中使用同步来保护要使用的共享的数据,也会使系统的性能大大下降。这是因为被同步的代码块在同一时刻只能有一个线程执行它,使得其同时处理客户请求的吞吐量降低,而且很多客户处于阻塞状态。另外为保证主存内容和线程的工作内存中的数据的一致性,要频繁地刷新缓存,这也会大大地影响系统的性能。所以在实际的开发中也应避免或最小化 Servlet 中的同步代码;在Serlet中避免使用实例变量是保证Servlet线程安全的最佳选择。从Java 内存模型也可以知道,方法中的临时变量是在栈上分配空间,而且每个线程都有自己私有的栈空间,所以它们不会影响线程的安全。
  小结
  Servlet的线程安全问题只有在大量的并发访问时才会显现出来,并且很难发现,因此在编写Servlet程序时要特别注意。线程安全问题主要是由实例变量造成的,因此在Servlet中应避免使用实例变量。如果应用程序设计无法避免使用实例变量,那么使用同步来保护要使用的实例变量,但为保证系统的最佳性能,应该同步可用性最小的代码路径。

三、JSP中线程安全
JSP的本质是Servlet,所有只要明白了Servlet的安全问题,JSP的安全问题应该很容易理解.使用<%! %>声明的变量是Servlet的实例变量,不是线程安全的,其他都是线程安全的.
<%! String unsafeVar; %> //不是线程安全的
<% String safeVar; %>      // 线程安全的

    总结:线程安全问题主要是由实例变量造成的,不管在Servlet还是JSP,或者在Struts的Action里面,不要使用实例变量,任何方法里面都不要出现实例变量,你的程序就是线程安全的.

分享到:
评论

相关推荐

    吉林大学珠海学院JSP&Servlet学习笔记(第二版)课后答案

    本笔记共分为九章,每章节都包含了相关的问题答案,涉及到JSP和Servlet的各个方面。 在第一章中,本笔记涵盖了JSP的基本概念,包括JSP的历史发展、JSP的特点、JSP的基本结构等。同时,本章节还介绍了JSP的生命周期...

    JSP和Servlet面试题

    6.如何处理Servlet的线程不安全问题 1.最简单的就是不使用字段变量, 2.使用final修饰变量, 3.线程安全就是多线程操作同一个对象不会有问题,线程同步一般来保护线程安全, 所以可以在Servlet的线程里面加上同步...

    JAVA WEB 开发详解:XML+XSLT+SERVLET+JSP 深入剖析与实例应用.part2

    本书共分4部分,从xml、servlet、jsp和应用的角度向读者展示了java web开发中各种技术的应用,循序渐进地引导读者快速掌握java web开发。.  本书内容全面,涵盖了从事java web开发所应掌握的所有知识。在知识的讲解...

    JAVA WEB 开发详解:XML+XSLT+SERVLET+JSP 深入剖析与实例应用.part3

    本书共分4部分,从xml、servlet、jsp和应用的角度向读者展示了java web开发中各种技术的应用,循序渐进地引导读者快速掌握java web开发。.  本书内容全面,涵盖了从事java web开发所应掌握的所有知识。在知识的讲解...

    JAVA WEB 开发详解:XML+XSLT+SERVLET+JSP 深入剖析与实例应用.part4

    本书共分4部分,从xml、servlet、jsp和应用的角度向读者展示了java web开发中各种技术的应用,循序渐进地引导读者快速掌握java web开发。.  本书内容全面,涵盖了从事java web开发所应掌握的所有知识。在知识的讲解...

    JSP/Servlet Java面试逻辑题

    7、JSP和Servlet有哪些相同点和不同点,他们之间的联系是什么? 答:JSP是Servlet技术的扩展,本质上是Servlet的简易方式,更强调应用的外表表达。JSP编译后是类servlet。Servlet和JSP最主要的不同点在于,Servlet...

    JAVA WEB 开发详解:XML+XSLT+SERVLET+JSP 深入剖析与实例应用.part5

    本书共分4部分,从xml、servlet、jsp和应用的角度向读者展示了java web开发中各种技术的应用,循序渐进地引导读者快速掌握java web开发。.  本书内容全面,涵盖了从事java web开发所应掌握的所有知识。在知识的讲解...

    Java开发指南——Servlet和JSP篇

    Java在Web应用程序开发方面的巨大潜力已日趋明显,其具有多线程执行,内存管理,面向对象性和强大的标准库。本书首先介绍Servlet API,JSP API基础知识,接着讲解如何进行对话跟踪盒调试,以及XML盒使用企业...

    ebook(servlet+jsp , sqlserver2005 )

    Book(购物车,监听器,jdni,线程副本,过滤器,分页,jquery,ajax,servlet+jsp , sqlserver2005 )

    基于JSP/Servlet校园二手交易平台

    本系统采用JSP/servlet技术,是使用Java编程语言编写的一套校园网二手交易平台软件。系统采用的是最近几年流行的B/S开发模式,以互联网方式运行,服务器端只需要安装本系统,而客户端用户只要可以上网,就可以非常...

    Java面试-线程编程、Jsp、Servlet、Jdbc、Jdo、Xml方面.doc

    Java面试-线程编程、Jsp、Servlet、Jdbc、Jdo、Xml方面.doc

    实验9 Servlet.doc

    本专栏主要为Java程序设计(基础)实验报告和Java程序设计(进阶)...进阶篇有反射、泛型、注解、网络编程、多线程、序列化、数据库、Servlet、JSP、XML解析、单例模式与枚举。本专栏主要为Java入门者提供实验参考。

    bookstore:基于JDBC+Servlet+JSP的网上书城

    bookstore 通过表单的隐藏域保存...因为是先得到购物车,可能因为多线程的问题修改了书的数量。即: int storeNumber = sci.getBook().getStoreNumber(); // 错误 int storeNumber = new BookService().getBook(sci.

    Java多线程与线程安全实践-基于Http协议的断点续传.zip

    标签库能增强功能和服务器性能,而且不受跨平台问题的限制。JSP文件在运行时会被其编译器转换成更原始的Servlet代码。JSP编译器可以把JSP文件编译成用Java代码写的Servlet,然后再由Java编译器来编译成能快速执行的...

    JAVA笔试面试资料JDBC HTTP、JSP、Servlet、Struts面试题汇总资料.zip

    Java基础、Java集合、多线程、JDBC、HTTP、JSP、Servlet、Struts面试题汇总(附答案).docx java工程师面试题大全-100%公司笔试题你都能碰到几个.docx Java开发工程师上机笔试题.docx Java开发求职面试题.docx Java...

    Java基础、Java集合、多线程、JDBC、HTTP、JSP、Servlet、Struts面试题汇总(附答案).docx

    Java基础、Java集合、多线程、JDBC、HTTP、JSP、Servlet、Struts面试题汇总(附答案).docx

    JSP訳文--工具--Java

    UltraEdit 7.2 WebGain Studio 4 with VisualCafe Forte for Java开发指南 Dreamweaver UltraDev IBM NetObjects ScriptBuilder3.0 使用HomeSite加速JSP的开发 Java2的安全新特性下的Applet...

Global site tag (gtag.js) - Google Analytics