2014-04-20 33 views
0

说,我有一个声明为全局字符串变量的TestServlet类。如果同时调用TestServlet类,这个'message'字符串变量是否可以安全地打印而不会从并发线程中穿过?HttpServlet.class是否以线程安全的方式运行?

public class TestServlet extends HttpServlet { 

    private String message; 

    public void doGet(HttpServletRequest request, 
        HttpServletResponse response) throws ServletException, 
                 IOException { 

     OutputStream os = response.getOutputStream(); 
     message = UUID.randomUUID().toString(); 
     os.write(message.getBytes()); 
    } 


} 
+0

它跨多个线程共享。为什么你需要把它变成一个实例变量?为什么你不在'String message = UUID.randomUUID()。toString();'方法中? –

+0

因为实例变量将被用于其他目的。 – lannyboy

回答

3

一个servlet是跨请求共享的,所以不,它不是线程安全的。 servlet对象的作用域为web.xml中的<servlet>声明。

容器为每个servlet创建一个<servlet-class>实例并调用其方法init

这里一些参考:

http://www.coderanch.com/t/473015/Servlets/java/Servlet-thread-safe

http://docs.oracle.com/javaee/5/tutorial/doc/bnafu.html

一般来说,如果你是在一个servlet存储状态,你应该考虑的替代品。为什么在那里存储状态什么是状态绑定?它与请求绑定吗?如果是这样,请使用request.setAttribute。如果它旨在由同一用户在多个请求之间共享,请使用request.getSession().setAttribute。如果它应该被所有请求共享,那么request.getServletContext().setAttribute

如果状态只针对一个请求,而且只在执行此servlet的时候,那么它应该只是方法中的局部变量。例如:

public void doGet(HttpServletRequest request, 
        HttpServletResponse response) throws ServletException, 
                IOException { 

     OutputStream os = response.getOutputStream(); 
     String message = UUID.randomUUID().toString(); 
     os.write(message.getBytes()); 
    } 

注意这里没有非局部变量。这是相当线程安全的。

+0

感谢您的解释。 – lannyboy

1

不,servlet不是线程安全的。 Servlet不应该以这种方式公开任何种类的可变状态。