[关闭]
@867976167 2014-10-11T14:39:57.000000Z 字数 1716 阅读 1969

Servlet的线程安全性

Servlet,多线程


首先说明Servlet并非线程安全,在所有对某个url的请求全部被转发到同一个Servlet。所以在开发Servlet过程尽量不使用实例变量,而使用局部变量。虽然在整个应用过程中只有一个Servlet,但是Servlet并不是单例模式,Server只是被容器创建一次,所以才只存在一个Servlet实例。
下面简单介绍Servlet请求过程主要参考stackoverflow的一个回答:

当容器启动时候:

1.读取web.xml文件,根据Servlet的 load-on-startup属性确定是否启动,非负时候Servlet会被启动。
2.获得Servlet的路径
3.加载并且实例化Servlet,只实例化一次

就如下面:

  1. String urlPattern = parseWebXmlAndRetrieveServletUrlPattern();
  2. String servletClass = parseWebXmlAndRetrieveServletClass();
  3. HttpServlet servlet = (HttpServlet) Class.forName(servletClass).newInstance();
  4. servlet.init();
  5. servlets.put(urlPattern, servlet); // Similar to a map interface.

Those Servlets are stored in memory and reused every time the request URL matches the Servlet's associated url-pattern. The servlet container then executes code similar to:

这些Servlet被加载到内存,每次请求都会使用相同的servlet。容器将会执行如下代码:

  1. for (Entry<String, HttpServlet> entry : servlets.entrySet()) {
  2. String urlPattern = entry.getKey();
  3. HttpServlet servlet = entry.getValue();
  4. if (request.getRequestURL().matches(urlPattern)) {
  5. servlet.service(request, response);
  6. break;
  7. }
  8. }

service根据请求类型(post,get)转发到相应方法doGet,doPost;
Servlet容器对于相同的请求使用的是同一Servlet,即Servlet被共享给每个request。所以应该注意:

1.不用实例变量。
2.不要在Servlet的方法加  synchronized关键字.
  1. public class MyServlet extends HttpServlet {
  2. private Object thisIsNOTThreadSafe;
  3. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  4. Object thisIsThreadSafe;
  5. thisIsNOTThreadSafe = request.getParameter("foo"); // BAD!!所有请求共享
  6. thisIsThreadSafe = request.getParameter("foo"); // OK, 线程安全
  7. }
  8. }

通过实现SingleThreadModel接口,可以每次请求都创建一个新的Servlet,但由于静态变量和session,依然存在线程安全性问题。所以此接口不推荐使用。
session不是线程安全的,当同一用户在不同浏览器请求时候可能导致线程问题。

Struts的线程安全

1.Struts1不是线程安全的;Struts1的Action是单例模式,每次请求使用一个Action。Struts1太老,认为创建新的实例花费太大,所以使用单例模式。
2.Struts2是线程安全的;每次请求创建新的Action,线程安全。
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注