回到顶部
您的当前位置: 编程语言> JAVA> JAVA基础> WEB开发
Servlet技术-线程安全问题
2014-04-18 17:24:49
标签: 原创 Servlet 开发 线程安全

    Servlet引擎采用多线程模式运行,它为并发的每个访问请求都预备一个独立的线程来进行响应。Servlet引擎采用的多线程模式可以提高访问的性能,但也带来了线程的安全问题。例如,如果并发的多个请求访的是同一个Servlet,那么将有多个线程来并发调用该Servlet的service方法。

Public class ThreadServlet extends HttpServlet{//统计访问次数
    private int count=0;
    public void service(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
        count++;
        try{
            Thread.sleep(500);
        }catch(Exception e){
            System.out.println(“这是第“+count+”次访问“+”,这次访问的线程名称是:“+Thread.currentThread().getName());
        }
    }
}

public class ThreadServlet extends HttpServlet {
    private int count=0;
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        synchronized(this){
            count++;
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(count);
        }
    }
}
SingleThreadModel接口

    Servlet API中定义了一个javax.servlet.SingleThreadModel接口,如果某个Servlet实现了这个接口,那么Servlet引擎将以单线程模式来调用其service方法。保证其单个实例对象的service方法不会同时被两个线程调用,但是,Servlet引擎仍然支持对该Servlet的多线程并发访问,其采用的方式是生产多个Servlet实例对象,并发的每个线程分别调用独立的Servlet实例对象,这样,可以同时有多个Servlet实例对象并发运行,每个Servlet实例对象的service方法都不会被多个线程并发调用。实现了SingleThreadModel接口的Servlet的多个实例对象共同组成一个Servlet对象池,当Web容器接收到针对该Servlet的访问请求时,将从Servlet对象池中挑选一个空闲的Servlet实例对象进行响应。实现SingleThreadModel接口并不能真正解决Serlet的线程安全问题,因为Servlet引擎会创建多个Servlet实例对象,多个并发的请求分别由不同的Servlet实例对象处理,或者被单个Servlet实例对象啄个依次排队处理,而真正意义上的多线程安全问题是指一个Servlet实例对象被多个线程同时调用的问题。所以,如果多个并发的service方法调用有线程安全问题,最好是自己在service方法中编写多线程的同步控制代码,而不是才用单线程的模式运行。

    实现SingleThreadModel接口

Public class ThreadServlet extends HttpServlet implements SingleThreadModel{//统计访问次数
    private int count=0;
    public void service(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
        count++;
        try{
            Thread.sleep(500);
        }catch(Exception e){
            System.out.println(“这是第“+count+”次访问“+”,这次访问的线程名称是:“+Thread.currentThread().getName());
        }
    }
}
哪些情况下要考虑线程安全问题

    在Servlet程序中除了访问成员变量时要注意线程安全问题,访问其他共享资源时也要注意线程安全问题,例如,Web应用程序对象,Session对象,数据库等都可能涉及多个Servlet线程同时访问的问题,如果servlet中没有定义成员变量和service方法中没有访问无同步访问控制的共享数据时,即使多个线程并发调用service方法,也不会存在任何线程安全问题。