最好基于多线程的角度来考虑谢谢了

解决方案 »

  1.   

    每个servlet都是一个线程,他把request和response对象分别发送到服务端和客户端, servlet把request和response发送到服务端和客户端后被清除. request根据需要决定是否存放在session中. 如果没有存放在session中,第二次请求request重新生成,放入SESSION中,采用同一个request
      

  2.   


    这个问题很有意义!他将牵扯到Servlet的编程模型以及 Servlet 的内在运行机制 !
    对于对 servlet 的底层认识很是有必要 !首先 Tomcat 服务器启动时 容器加载 Servlet 实例
    同时 调用初始化方法 into(); 然后 Servlet 等待服务, 当客户端发送一个请求时
    调用实例的服务方法 Serice();(方法本身进行判断是Post请求呢 还是请求Get请求,然后调用相关方法。 如doPost() )直到服务器关闭,然后调用系统的垃圾回收机制方法 destroy();进行销毁, 整个过程是一种基于 " 一次实例 ,多次服务 " 的。愿我对于 Servlet 的底层以及 原理性的运行机制对于你 对于Servlet的认识有一个更加深入的理解 !
    谢谢.....
      

  3.   

    对我2楼的贴子发表更正.
    Servlet如3楼所说,servlet一般只会有一个实例,每次交互并不会消除.servlet是作为一个媒介,而内容责是request和response
      

  4.   

    谢谢朋友们2楼的朋友,你说的我有点不太明白,可否详细点:
    我个人的了解如下,请你check:
      request ,response是由web服务器生成,并把它们传给servlet,web容器为每一次servlet请求,产生一个对应的线程,(这可否理解为你说的:每个servlet都是一个线程
    但是你说的:他把request和response对象分别发送到服务端和客户端, 我不太理解,我的理解是,servlet中,根据request对象获取对应客户端发送过来的信息;根据response对象,把生成的信息回传给客户端,  
    一个servlet执行完后,其对象会清除吗?
    servlet把request和response发送到服务端和客户端后被清除. ,如何理解呢?多谢,多谢
      

  5.   

    3楼的朋友说得很细,收益
    辛苦了按照你的话,可否总结为,一个servlet实例一旦生成,直到web容器停止运行,其对象才会从内存中消失另外,你说的:“ 整个过程是一种基于 " 一次实例 ,多次服务 " 的。 ”
    可否理解为: 对于每一次的连接请求(既是一个线程),都调用同一个servlet实例,也就是说它是单例模式请check,check多谢
      

  6.   

    1. 这可否理解为你说的:每个servlet都是一个线程
    你的理解与我的有些偏差,servlet不是web服务器生成的,web服务器是根据请求中的URL中找到正确Servlet,web服务器为其创建或者分配一个线程,同时把2创建的两个对象(request,response)传递给该线程.
    2. 他把request和response对象分别发送到服务端和客户端
    request,response是在服务器端生成的,web服务器主线程对用户的请求做出响应创建两个对象:HttpServletRequest和HttpServletResponse;
    3.servlet把request和response发送到服务端和客户端后被清除
    这点我也不是很清楚,不过上网查了下,servlet对象在执行交互后是会调用destory()方法然后被清楚的,也就是一次请求发送后,当servlet 的service 方法内的所有线程都退出的时候,servlet对象被消除.
      

  7.   

    3.servlet把request和response发送到服务端和客户端后被清除 
    这点我也不是很清楚,不过上网查了下,servlet对象在执行交互后是会调用destory()方法然后被清楚的,也就是一次请求发送后,当servlet 的service 方法内的所有线程都退出的时候,servlet对象被消除.
    你说的这点我也比较认同,3楼的一个朋友说的:“直到服务器关闭,然后调用系统的垃圾回收机制方法 destroy(); ”,如果每个servlet对象一旦生成,就一直存在,会不会太占用内存?  疑惑中,求正解?
      

  8.   

    同意3楼的大部分看法,不过对destroy()方法执行的时间保留意见。
    请参看http://topic.csdn.net/u/20081017/15/26842176-f322-4a8d-9b93-eb8ff0ed9c2b.html
      

  9.   

    这个方法只有在servlet的service方法内的所有线程都退出的时候,或在超时的时候才会被调用。
      

  10.   

    <<jsp网络编程>> 上有一句话,
    ”web容器只会构建唯一一个Servlet对象,但所有的处理对都由它完成“不是太理解,
    一个servlet怎会处理所有的请求(当然是针对这个servlet)我的理解是: web容器为每一个请求创建一个基于socket的线程对象,该线程中会用这个servlet来处理, 还请高人明示:?
      

  11.   

    寻求oracle,db2,sql2005,delphi,pb,websphere,weblogic,eclipse,vc++,Linux,IBM AIX,office高手兼职培训讲师,感兴趣发简历至:[email protected]  http://www.ciitc.com
      

  12.   

    我也是初学者,最近在看jsp与servlet核心编程。我的理解是浏览器向服务器发送请求,请求中会指明这个请求需要交给哪个servlet处理。服务器收到请求,按照请求的要求交给某个servlet处理,(至于第一次请求的时候servlet是不是在内存里,我不知道),servlet在服务器中只有一个实例,每个请求会获得一个线程运行这个实例(这也是为什么对于一些操作步骤要synchronize,因为线程的轮换执行可能会对同一个servlet的共享的数据造成混乱)。至于什么时候destroy,我不清楚。希望大家继续讨论。
      

  13.   

    servlet是不是有个池的概念?  因为servlet的 doGet()和doPost()方法是运行在多线程下的,所以一个servlet实例可以处理多个请求,而他的 init()初始化方法则是同步的。  在长时间没有被调用(具体多长时间不清除)或者 服务器关闭时,servlet实例销毁了。
      

  14.   

    我的理解,Servlet中的request,response包含当前线程的锁,在多线程的情况下,Servlet虽然是同一个对象,可是request和response不是,他们分别拥有各自线程的锁,所以当多个线程对Servlet进行调用的时候,request和response是分别对应的当前线程的锁,这样就不会导致线程1可以访问线程2的request和response。
      

  15.   

    <<Head First Servlet&JSP>>上说,容器运行多个线程来处理一个Servlet的多个请求.
    而request,response是封装在线程里,由容器传给Servlet的.
    request是线程安全的吗? 是的.
    在servlet的生命周期中,它的实例始终只有一个.
    servlet是由容器调用它的init()方法,同样,也是由容器调用它的destory().
      

  16.   

    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
      

  17.   

     当用户发起第一次请求某个servlet时,servlet容器会创建某个servlet的实例,而且这个实例会常驻服务器内存中
     当再有新的用户发起请求同一个servlet时,servlet容器不会再创建该servlet的实例 servlet运行机制: 单实例,多线程模式
      

  18.   

    servlet并不是一个线程,只能说是类似线程。是容器启动线程,根据请求调用servlet。而处理完请求后,线程会被容器回收。
      

  19.   

    请参考我们教程中的相关内容
    http://family168.com/tutorial/jsp/html/jsp-ch-14.html
      

  20.   

    servlet是首次加载后,生成了相关对象保存在web容器中,该对象是灌注整个web容器的始终,直到web容器关闭。可以参考servlet的生命周期,该对象被实例化后保存在web容器中,当有请求时web容器先截获,然后web容器开启一条线程去servlet的map集合里根据request报头寻找相关的servlet处理请求,该线程是一直处理该request,直到处理结束,响应请求。该线程结束,但是servlet对象是不会被销毁的,他还是保留在web容器中。多个请求同一servlet时就是开启多条线程响应请求。
      

  21.   

    真的没有人了解JAVA线程池吗?servlet在线程池中只起着Callbale的作用。
     一次请求进来首先被转换成RequestTask对象放在请求对列中。
    只有处理线程从队列中get这个RequestTask并调用它的业务方法时,才会调用对应的servlet的服务方法。在同一时刻,一个servlet只有一个实例(2.4以前可以有多少实例来实现单线程安全的servlet),但在容器生命
    周期内,不是只有一个实例。因为容器可以根据需要对长时间没有被请求的servlet实例销毁,在必要的时候再生成。client request-> listener->put RequestTask(ServletHandler) into QueueWorkThread -> take RequestTask ->wrap Request/Response -> invoke Callbale(service method).
      

  22.   

    关于这个问题,三楼说得不错,只是有些地方要改下
    into() -> init();
    Serice() -> service();
      

  23.   

    37楼朋友提供的一个例子: 很好,有助于理解servlet的多线程,  但看这段小程序,想想会出现什么问题?
    -------------------------package anni;import java.io.IOException;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;public class TestServlet extends HttpServlet {    private String username;    public void doGet(HttpServletRequest request,
                        HttpServletResponse response)
                throws ServletException, IOException {
            this.username = request.getParameter("username");        try {
                Thread.sleep(10000);
            } catch(InterruptedException ex) {
            }        response.getWriter().write(this.username);
        }}
      

  24.   

    Servlet 是单实例,多线程设计的;有成员变量不同步当然有安全问题,但是有同步会影响性能,所以要避免  --和连接池相似
    servlet 是基于摸板设计模式 --有的也叫 回调机制;如果人为的覆盖service ,必须要显示调用super 否则无效
      

  25.   

    这个username不是线程安全的,它可能被多个线程访问到.
    因此,在你读了username,休眠,再写username的时候,可能会发现此username非彼username了.
      

  26.   

    我觉得41楼的是正解
    同一时间是只有一个servlet实例
    在这个期间没有被销毁的话 来的请求都是使用同一个实例
    如果是成员变量 肯定会造成混乱
    不过没有请求的时候web容器会自动销毁servlet实例
      

  27.   

    在同一时刻,一个servlet只有一个实例(2.4以前可以有多少实例来实现单线程安全的servlet),但在容器生命 
    周期内,不是只有一个实例。因为容器可以根据需要对长时间没有被请求的servlet实例销毁,在必要的时候再生成。 
    --------
    这个好
      

  28.   

    =====init=======
    =======run==========
    =======run==========
    =======run==========
    =======run==========
    =======run==========
    =======run==========
    =======run==========
    =======run==========
    =======run==========
    =======run==========
    =======run==========
    =======run==========
    =======run==========
    =======run==========
    =======run==========
    =======run==========
    =======run==========
    2009-3-23 15:56:53 org.apache.coyote.http11.Http11Protocol pause
    信息: Pausing Coyote HTTP/1.1 on http-80
    2009-3-23 15:56:54 org.apache.catalina.core.StandardService stop
    信息: Stopping service Catalina
    =====destroy=======上面是我做的一个测试init输出是在web服务器加载servlet执行类时执行的。
    中间做了一系列的操作,响应回来后并没有销毁实例,当我关闭web服务器的时候
    destroy才输出。楼主可否有帮助呢。
      

  29.   

    首先是web容器加载创建servlet,然后调用init()方法进行初始化,在调用doService方法进行服务这时候需要确定调用doPost还是doGet,根据请求方式的不同而不同,(注意:此时,servlet实例并没有销毁,进行多次服务的),当容器关闭的时候,调用destroy方法回收对象.
      

  30.   

    =====init======= 
    =======run========== 
    =======run========== 
    =======run========== 
    =======run========== 
    =======run========== 
    =======run========== 
    =======run========== 
    =======run========== 
    =======run========== 
    =======run========== 
    =======run========== 
    =======run========== 
    =======run========== 
    =======run========== 
    =======run========== 
    =======run========== 
    =======run========== 
    2009-3-23 15:56:53 org.apache.coyote.http11.Http11Protocol pause 
    信息: Pausing Coyote HTTP/1.1 on http-80 
    2009-3-23 15:56:54 org.apache.catalina.core.StandardService stop 
    信息: Stopping service Catalina 
    =====destroy======= 上面是我做的一个测试init输出是在web服务器加载servlet执行类时执行的。 
    中间做了一系列的操作,响应回来后并没有销毁实例,当我关闭web服务器的时候 
    destroy才输出。楼主可否有帮助呢。------------------
    朋友辛苦, 可否提供源代码,及你的测试方式,比如对同一个servlet你是间隔多久才链接,还是频繁链接?
      

  31.   

    1.Servlet默认是第一次请求到的时候才创建,可以设置成服务器启动时就创建,可以在web.xml中的<servlet>下添加<load-on-startup>2</load-on-startup>数字越小的越先加载2.init()方法在servlet对象创建后被web容器调用一次3.service()或者是doGet(),doPost()等方法,在每次请求到来时被调用,这些方法是运行的在多线程状态下的,必须注意同步4.在长时间没有被调用或者是服务器关闭时,web容器会调用destroy()方法来销毁Servlet对象。
      

  32.   

    Servlet是线程不安全的,所以是一次实例多次服务。
      

  33.   

    不会删除,每次来请求都建立个线程来处理请求,因为线程共享资源,所以速度快一些,直至服务器重启都会使用这个sevlet对象。
      

  34.   

    看看大家的观点,总结:1.servlet在整个生命周期是一个实例,在第一次请求时创建或者有web.xml的加载等级确定,具体是否“长时间没有被调用则关闭”,则由web服务器实现。
    2.request和response对象对于每个请求都会有单独的实例。
    3.每个用户的请求,tomcat分配了一个线程给这个用户,在这个线程里面创建request和response对象,并调用servlet实例的service方法!当service方法调用结束,tomcat回收了线程放回线程池,分配给新用户使用。在这个线程里面创建的实例被垃圾回收器在适当时间回收。
    4.servlet的成员变量是:线程不安全的,所以尽量不要定义成员变量!当然实现“访问量计数器”可以这样做!
    5.init和destroy方法在servlet的生命周期中只会被调用一次。
      

  35.   

    总的来说,servlet就是一个实例,多线程的,其中init()方法只执行一次,每次有请求时执行一次service()方法,最后结束时执行destroy()方法
      

  36.   

    我来补充一下  拿tomcat来说 当tomcat启动的时候,会寻找servlet类文件,可能是在容器启动的时候也可能是在第一个用户使用时进行加载。加载的时候调用init()方法实例化一个servlet对象,然后如果客户有请求,就调用service()方法来处理容器传过来的请求和响应,servlet处理完成以后会修改响应,并传递响应到相应的JSP或其他的servlet,容器穿过来的请求这时候就作废了
      

  37.   

    忘记说了,如果有请求到来的时候,容器创建或分配一个servlet线程处理请求和响应,当service()方法结束,对应的servlet线程要么撤销(当servlet实例下没有其他线程的时候),要么就回到容器管理的一个线程池中。 servlet生命周期中init()方法只调用了一次,distory()方法只是调用一次
      

  38.   

    61楼总结的很好! 我补充一下,servelt容器初始时会把定量的实例放到实例池中,具体放多少个是可以配置的,对于每一个请求过来,它并不关心为之服务的实例是具体哪一个,所以在servlet编程中要注意线程安全的问题,我以前有个同事写servlet的时候就在servlet里写实例变量,所以大家以后不要犯这种低级错误!
    LZ的求知态度值得欣赏!