最近在看线程的有关知识,碰到一个小问题,目前还没有解决,现记录下来。
如果在我们自己写的servlet里有成员变量,因为多线程的访问就会出现一些线程问题。这点大家都知道,我们看下面的例子。
public class ConcurrentTest extends HttpServlet { PrintWriter output; @Override protected 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); output.println("用户名:"+username+"<BR>"); } catch (Exception e) { e.printStackTrace(); } } }
部署在tomcat7上
然后我们在浏览器上发两个链接。
a: http://localhost:8080/ServletTest/ConcurrentTest?Username=a
b: http://localhost:8080/ServletTest/ConcurrentTest?Username=b
当a发送后,过半秒后发送b。
我们可以看到a请求的返回页是什么都没有
而b上显示
用户名:a
用户名:b
为什么会有这个效果是因为,a请求的output这个变量在多线程的情况下被b线程的output覆盖了。所以"两个"(其实只有一个)servlet的输出流对象都定位到b上面了。
这是一个经典的例子。
再看下面这个。
public class SimpleServlet extends HttpServlet{ // A variable that is NOT thread-safe! private int counter = 0; public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.getWriter().println("<HTML><BODY>"); resp.getWriter().println(this + " ==> "); resp.getWriter().println(Thread.currentThread() + ": <br>"); for (int c = 0; c < 10; c++){ resp.getWriter().println("Counter = " + counter + "<BR>"); try { Thread.sleep((long) Math.random() * 1000); counter++; } catch (InterruptedException exc){} } resp.getWriter().println("</BODY></HTML>"); } }
和第一个例子似乎差不多,只是变量由PrintWriter变成了int。
我们在做三个请求。
<HTML> <BODY> <TABLE> <TR> <TD><IFRAME src="./SimpleServlet" name="servlet1" height="200%"> </IFRAME></TD> </TR> <TR> <TD><IFRAME src="./SimpleServlet" name="servlet2" height="200%"> </IFRAME></TD> </TR> <TR> <TD><IFRAME src="./SimpleServlet" name="servlet3" height="200%"> </IFRAME></TD> </TR> </TABLE> </BODY> </HTML>
在tomcat7下 结果是
[email protected]:
Counter = 0
Counter = 1
Counter = 2
Counter = 3
Counter = 4
Counter = 5
Counter = 6
Counter = 7
Counter = 8
Counter = 9
[email protected]:
Counter = 10
Counter = 11
Counter = 12
Counter = 13
Counter = 14
Counter = 15
Counter = 16
Counter = 17
Counter = 18
Counter = 19
[email protected]:
Counter = 20
Counter = 21
Counter = 22
Counter = 23
Counter = 24
Counter = 25
Counter = 26
Counter = 27
Counter = 28
Counter = 29
并没有出现我们想象中的乱序问题。
一种解释是tomcat7中使用了ThreadPoolExecutor技术。
但是我依然不明白,那为什么同是在tomcat7下,第一个例子就会出现覆写的问题呢?
这个问题,估计的看源码才行。
如果有哪位大侠知道问题的答案请告诉我,跪谢了。
参考资料
两个例子分别来自下面两个地址 详细信息大家自己去看看吧
http://www.cnblogs.com/gw811/archive/2012/09/07/2674859.html
http://zwchen.iteye.com/blog/91088