1、Servlet的特点:单实例多线程
Servlet(struts类似)的生命周期是由Web容器负责的,当客户端第一次请求Servlet时,容器负责初始化Servlet,也就是实例化这个Servlet 类。
以后这个实例就负责多个客户端的请求,一般不会再实例化一个Servlet类,也就是有多个线程在使用这个实例。
Servlet之所以比CGI效率高就是因为Servlet是多线程的。2、线程不安全
这就导致了Servlet里的实例变量是线程不安全的,多个线程(多个客户端的请求)共享这些实例变量,一个线程对这些实例变量的改变会影响其它线程的取值,
Servlet规范已经声明Servlet不是线程安全的,包括jsp,Servlet,javabean等。实例变量:是在堆中分配的,并被属于该实例的所有线程共享,所以不是线程安全的。
静态变量:不是线程安全的。
局部变量:方法中的局部变量是不会影响线程安全的,因为他们是在栈上分配空间,而且每个线程都有自己私有的栈空间3、Servlet规范 -- 如何使Servlet安全
使用synchronized同步方法,效率太低,一般不使用
使用单线程模型,如果该Servlet被声明为单线程模型的话,容器就会维护一个实例池,那么将存在多个实例,效率更低,一般不使用。
使用Servlet编程规范。以下列出几种不安全的情形以及Servlet(struts类似)规范:
--------------JSP------------JSP中用到的out,request,response,session,config,page,pageconxt是线程安全的,
application在整个系统内被使用,所以不是线程安全的. <%! String unsafeVar; %>   // 使用<%! %>声明的变量是Servlet的实例变量,不是线程安全的
<% String safeVar; %>      // 局部变量,线程安全--------------Servlet------------class ServletMain extends HttpServlet{

  private String strTest1;  // 实例变量,线程不安全,只读(客户线程不能改变其值)可用,否则不能使用。
  
  private static final String strTest2 = "TEST";  // 静态变量,但只读,线程安全,可用。
  
  private Config config;  // 实例变量,如果是只读,线程安全,可用。
  
  public void init() throws ServletException {
   String strTest3;        // 局部变量,线程安全
  }
 ...
 
-----------Action---------------public class TestAction extends ActionController {

  private String strTest1;  // 实例变量,线程不安全,只读(客户线程不能改变其值)可用,否则不能使用。
  
  private static String strTest2 = "TEST";  // 静态变量,线程不安全,只读(客户线程不能改变其值)可用,否则不能使用。
    
  public void test() throws ServletException {
   String strTest3;        // 局部变量,线程安全
  }
 ...
 
--------------------------

解决方案 »

  1.   

    struts1.x的action是多线程单实例的,struts2.x的action是多线程多实例的,是一直有这么个疑问,就是不同规模的项目对这两种方案的取舍,还有这两种方案在性能上的差异
      

  2.   

    这个早有解决方案了,用 ThreadLocal,我博客中就有文章介绍使用。一时早不到链接了,你到 Google下吧,很多。
      

  3.   

    用spring可以控制线程安全,用单例。
    也可以用isThreadSafe设置线程安全