分类: Java
2011-05-19 11:52:50
首先我们必须要先了解servlet的生命周期:
服务器只创建每个servlet的单一实例,首次创建servlet时,它的init方法会被调用,因此,init是放置一次性设置代码的地方,之后,针对每个用户的请求都会创建一个线程,该线程调用前面创建的实例方法。多个并发请求一般会导致多个线程同时调用service(线程安全),service方法会依据接受到HTTP请求的类型,调用doXXX方法。最后如果服务器卸载某个servlet就会调用servlet的destroy方法。
servlet是否线程安全?
通常情况下,系统只生成servlet的单一实例之后,为每个用户请求建立新的线程。如果很多请求同时到来,那么多个线程可能会并发的访问同一个servlet对象。因此我们必须小心地同步对字段以及全局变量和其它共享数据的访问,因为多个线程可能同时对同一数据进行访问。(多个线程并不共享局部变量)。
Servlet/JSP技术和ASP、PHP等相比,由于其多线程运行而具有很高的执行效率。由于Servlet/JSP默认是以多线程模式执行的,所
以,在编写代码时需要非常细致地考虑多线程的安全性问题。然而,很多人编写Servlet/JSP程序时并没有注意到多线程安全性的问题,这往往造成编写
的程序在少量用户访问时没有任何问题,而在并发用户上升到一定值时,就会经常出现一些莫明其妙的问题。
Servlet的多线程机制
Servlet体系结构是建立在Java多线程机制之上的,它的生命周期是由Web容器负责的。当客户端第一次请求某个Servlet
时,Servlet容器将会根据web.xml配置文件实例化这个Servlet类。当有新的客户端请求该Servlet时,一般不会再实例化该
Servlet类,也就是有多个线程在使用这个实例。Servlet容器会自动使用线程池等技术来支持系统的运行,如图1所示。
图1 Servlet线程池 |
Import javax.servlet. *; Import javax.servlet.http. *; Import java.io. *; Public class Concurrent Test extends HttpServlet {PrintWriter output; Public void service (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String username; Response.setContentType ("text/html; charset=gb2312"); Username = request.getParameter ("username"); Output = response.getWriter (); Try {Thread. sleep (5000); //为了突出并发问题,在这设置一个延时 } Catch (Interrupted Exception e){} output.println("用户名:"+Username+" "); } } |
图2 a用户和b用户的浏览器输出 |
图3 Servlet实例的JMM模型 |
调度时刻 | a线程 | b线程 |
T1 | 访问Servlet页面 | |
T2 | 访问Servlet页面 | |
T3 | output=a的输出username=a休眠5000毫秒,让出CPU | |
T4 | output=b的输出(写回主存)username=b休眠5000毫秒,让出CPU | |
T5 | 在用户b的浏览器上输出a线程的username的值,a线程终止。 | |
T6 | 在用户b的浏览器上输出b线程的username的值,b线程终止。 |
Public class Concurrent Test extends HttpServlet implements SingleThreadModel { ………… } |
………… Public class Concurrent Test extends HttpServlet { ………… Username = request.getParameter ("username"); Synchronized (this){ Output = response.getWriter (); Try { Thread. Sleep (5000); } Catch (Interrupted Exception e){} output.println("用户名:"+Username+" "); } } } |
…… Public class Concurrent Test extends HttpServlet {public void service (HttpServletRequest request, HttpServletResponse Response) throws ServletException, IOException { Print Writer output; String username; Response.setContentType ("text/html; charset=gb2312"); …… } } |