Servlet生命周期
1 生命周期
Servlet程序的生命周期由tomcat服务器控制的。一般情况下,第一次提交请求(request),会创建servlet,也是一个servlet的生命周期的开始。
构造方法: 创建servlet对象的时候调用。默认情况下,第一次访问servlet的时候创建servlet对象 只调用1次。证明servlet对象在tomcat是单实例的。
init方法: 创建完servlet对象的时候调用。只调用1次。
service方法: 每次发出请求时调用。调用n次。
destroy方法: 销毁servlet对象的时候调用。停止服务器或者重新部署web应用时销毁servlet对象。只调用1次。
2 servlet自动加载
默认情况下,第一次访问servlet的时候(即提交申请时)创建servlet对象。如果servlet的构造方法或init方法中执行了比较多的逻辑代码,那么导致用户第一次访问sevrlet的时候比较慢。为了解决这种状况,我们可以设置servlet的自动加载,把创建servlet的时候提前到加载web的时候。只需要在web.xml的servlet配置中加上一项<load-on-startup>即可。
<servlet> <servlet-name>LifeDemo</servlet-name> <servlet-class>gz.itcast.c_life.LifeDemo</servlet-class> <!-- 让servlet对象自动加载 --> <load-on-startup>1</load-on-startup> 注意: 整数值越大,创建优先级越低!! </servlet>
3 servlet多线程并发问题
注意: servlet对象在tomcat服务器是单实例多线程的。
因为servlet是多线程的,所以当多个servlet的线程同时访问了servlet的共享数据,如成员变量,可能会引发线程安全问题。
解决办法:
1)把使用到共享数据的代码块进行同步(使用synchronized关键字进行同步)
例:每此访问count都会+1,这就涉及多线程和线程安全问题。
1 public class TheradDemo extends HttpServlet { 2 3 int count = 1; 4 5 public void doGet(HttpServletRequest request, HttpServletResponse response) 6 throws ServletException, IOException { 7 response.setContentType("text/html;charset=utf-8"); 8 9 synchronized (TheradDemo.class) {//锁对象必须唯一。建议使用类对象 10 response.getWriter().write("你现在是当前网站的第"+count+"个访客"); //线程1执行完 , 线程2执行 11 12 //线程1还没有执行count++ 13 /*try { 14 Thread.sleep(5000); 15 } catch (InterruptedException e) { 16 e.printStackTrace(); 17 }*/ 18 count++; 19 } 20 } 21 22 }
2)建议在servlet类中尽量不要使用成员变量。如果确实要使用成员,必须同步。而且尽量缩小同步代码块的范围。(哪里使用到了成员变量,就同步哪里!!),以避免因为同步而导致并发效率降低。