Servlet生命周期与线程安全问题

Servlet生命周期分为四个阶段: 


1:构造方法: 创建servlet对象的时候调用。默认情况下,第一次访问servlet的时候创建servlet对象只调用1次。证明servlet对象在tomcat是单实例的。 
2:init方法: 创建完servlet对象的时候调用。只调用1次。 
3:service方法: 每次发出请求时调用。调用n次。 
4:destroy方法: 销毁servlet对象的时候调用。停止服务器或者重新部署web应用时销毁servlet对象。只调用1次。

public class ServletDemo {
	/**
	 * 伪代码演示servlet的生命周期
       Tomtcat内部代码运行:
	 		1)通过映射找到到servlet-class的内容,字符串: cn.itcats.MyServlet
	 		2)通过反射构造MyServlet对象*/
	//1、得到字节码对象
	Class clazz = Class.forName("cn.itcats.MyServlet");
	//2、调用无参数的构造方法来构造对象
	Object obj = clazz.newInstance();    //servlet的构造方法被调用
	//3、创建ServletConfig对象,通过反射调用init方法
	//3.1、得到方法对象
	Method init = clazz.getDeclareMethod("init",ServletConfig.class);
	//3.2 调用方法
	init.invoke(obj,config);             //servlet的init方法被调用
	//4、创建request,response对象,通过反射调用service方法
	//4.1 得到方法对象
	Method service  = clazz.getDeclareMethod("service",HttpServletRequest.class,HttpServletResponse.class);
	//4.2 调用方法
	service.invoke(obj,request,response);  //servlet的service方法被调用
	//5、当tomcat服务器停止或web应用重新部署,通过反射调用destroy方法
	//5.1 得到方法对象
	Method destroy = clazz.getDeclareMethod("destroy",null);
	//5.2 调用方法
	destroy.invoke(obj,null);            //servlet的destroy方法被调用
}

Servlet执行流程:

1、读取web.xml文件解析servlet

2、使用java的反射机制初始化servlet类

3、当发起servlet请求时候调用了HttpServlet父类service方法

4、通过service方法判断请求方式

5、子类重写了doGet方法,调用子类doGet方法

service和doGet方法有什么区别?

当发起servlet请求时,通过HttpServlet类的service方法判断请求方式,若为get请求,调用子类的doGet方法。

Servlet的多线程并发问题

注意: servlet对象在tomcat服务器是单实例多线程的。

由于通过反射机制,通过web.xml初始化类,默认调用无参构造函数,可以在自定义的Servlet类书写无参构造函数证明。

因为servlet是多线程的,所以当多个servlet的线程同时访问了servlet的共享数据,如成员变量,可能会引发线程安全问题。

解决办法:

 1)把使用到共享数据的代码块进行同步(使用synchronized关键字进行同步)

 2)建议在servlet类中尽量不要使用成员变量。如果确实要使用成员,必须同步。而且尽量缩小同步代码块的范围。(哪里使用到了成员变量,就同步哪里!!),以避免因为同步而导致并发效率降低。

 

猜你喜欢

转载自blog.csdn.net/itcats_cn/article/details/82291690