默认情况下,第一次访问servlet的时候创建servlet对象。 如果servlet的构造方法或init方法中执行了比较多的逻辑代码,那么就会导致用户第一次访问sevrlet的时候比较慢。
解决方法:改变servlet创建对象的时机,即提前到加载web应用的时候!!!
在servlet的配置信息中,加上一个<load-on-startup>即可!!
<servlet> <servlet-name>LifeDemo</servlet-name> <servlet-class>com.rk.http.b_lifecycle.LifeDemo</servlet-class> <!-- 让servlet对象自动加载 --> <load-on-startup>1</load-on-startup><!-- 注意: 整数值越大,创建优先级越低!! --> </servlet> <servlet-mapping> <servlet-name>LifeDemo</servlet-name> <url-pattern>/life</url-pattern> </servlet-mapping>
程序开发人员自定义的Servlet类,一般继承自javax.servlet.HttpServlet抽象类,而javax.servlet.HttpServlet类继承自javax.servlet.GenericServlet抽象类。javax.servlet.GenericServlet提供了两个init方法:
void init(ServletConfig config)
void init()
两者之间的简单关系如下:
    //有参数的init方法
    //该方法是servlet的生命周期方法,一定会被tomcat服务器调用
    //注意:如果要编写初始代码,不需要覆盖有参数的init方法
    public void init(ServletConfig config) throws ServletException {
		this.config = config;
		this.init();
    }
    
    //无参数的init方法
    //该方法是servlet的编写初始化代码的方法。
    //是Sun公司设计出来专门给开发者进行覆盖,然后在里面编写servlet的初始逻辑代码的方法。
    public void init() throws ServletException {
    }javax.servlet.GenericServlet类的部分源码如下:
package javax.servlet;
import java.io.IOException;
import java.util.Enumeration;
public class GenericServlet implements Servlet, ServletConfig, java.io.Serializable
{
	private transient ServletConfig config;
	
	/**
	 * Does nothing. All of the servlet initialization is done by one of the <code>init</code> methods.
	 */
	public GenericServlet() { }
	
	/**
	 * Called by the servlet container to indicate that the servlet is being placed into service.
	 */
    public void init(ServletConfig config) throws ServletException {
		this.config = config;
		this.init();
    }
    
    /**
     * A convenience method which can be overridden so that there‘s no need
     * to call <code>super.init(config)</code>.
     * 
     * Instead of overriding init(ServletConfig), simply override
     * this method and it will be called by <code>GenericServlet.init(ServletConfig config)</code>.
     * The <code>ServletConfig</code> object can still be retrieved via getServletConfig. 
     */
    public void init() throws ServletException {
    }
	
    /**
     * Returns this servlet‘s ServletConfig object.
     */
    public ServletConfig getServletConfig() {
    	return config;
    }
    
    public String getServletName() {
        return config.getServletName();
    }
    
	public String getInitParameter(String name) {
		return getServletConfig().getInitParameter(name);
	}
	
    public Enumeration getInitParameterNames() {
    	return getServletConfig().getInitParameterNames();
    }   
    
    /**
     * Returns a reference to the ServletContext in which this servlet is running.
     */
    public ServletContext getServletContext() {
    	return getServletConfig().getServletContext();
    }
}servlet对象在tomcat服务器是单实例多线程的。
因为servlet是多线程的,所以当多个servlet的线程同时访问了servlet的共享数据(如成员变量),可能会引发线程安全问题。
解决办法:
1)把使用到共享数据的代码块进行同步(使用synchronized关键字进行同步)
2)建议在servlet类中尽量不要使用成员变量。
a)如果确实要使用成员,必须同步;
b)尽量缩小同步代码块的范围,以避免因为同步而导致并发效率降低。(哪里使用到了成员变量,就同步哪里!!)
示例:记录页面访问次数
package com.rk.http.c_thread;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 * servlet的多线程并发问题
 * @author RK
 *
 */
public class ThreadDemo extends HttpServlet
{
	private int count = 0;
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
	{
		response.setCharacterEncoding("UTF-8");
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
//		out.write("<html><head><title>访问次数</title></head><body>这是第N次访问本页面</body></html>"); 
		out.write("<html><head><title>访问次数</title></head><body>这是第");
		synchronized (ThreadDemo.class)//锁对象必须唯一。建议使用类对象
		{
			try
			{
				Thread.sleep(3000);//这里模拟复杂的业务等待
			}
			catch (InterruptedException e)
			{
				e.printStackTrace();
			}
			count++;
			out.write("" + count);
		}
		out.write("次访问本页面</body></html>");
	}
}原文:http://lsieun.blog.51cto.com/9210464/1782118