这个图的执行代码是:package com.test;import java.io.IOException;
import java.io.PrintWriter;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/**
 * Servlet implementation class MyServlet
 */
@WebServlet("/MyServlet")
public class MyServlet extends HttpServlet {
private static final long serialVersionUID = 1L; 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(2000); // 为了突出并发问题,在这设置一个延时
} catch (InterruptedException e) {
}
output.println("用户名:" + username + "<BR>");
} /**
 * @see HttpServlet#HttpServlet()
 */
public MyServlet() {
super();
// TODO Auto-generated constructor stub
} /**
 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
 *      response)
 */
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
this.doPost(request, response);
} /**
 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
 *      response)
 */
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
this.service(request, response);
}}我不是理解图中T5,T6两步的解释。我个人认为在a,b两个窗口中都应该打印    用户名:b
但实际情况是b窗口打印了 a和b。求解

解决方案 »

  1.   

    T3的时候代码第19行的PrintWriter output对象为a的Writer对象.
    T4的时候代码第19行的PrintWriter output对象被替换为b的Writer对象.
    然后在T4运行过后b线程睡眠了2000毫秒, 所以在T5的时候是a线程在运行.
    而因为T4的时候b线程修改了output对象的值, 所以此时a线程的output对象其实是T4中b线程替换后的writer.
    所以T5和T6实际上都是往b客户端上打印.
      

  2.   

    难道response中有属性指定了浏览器地址?
      

  3.   

    servlet在web容器中是以单例形式存在的,你的两个线程访问的是同一个servlet对象,如果b线程修改了servlet对象的成员变量,这个过程对a线程是可见的,所以会出现你看到的结果。这也是servlet的一般要求是无状态的原因。
      

  4.   

    必须是a和b啊 你这同步没什么用,因为确实servlet存在线程安全问题,因为servlet是单列,但是你用的是局部变量 而不是成语变量,局部变量多线程下都有自己的拷贝是互不影响的所以是安全的所以打印结果是a和b,只有成语变量在单列的情况下才有多线程安全问题..
      

  5.   

    不是response绑定了浏览器地址. 而是因为servlet在服务器运行期间其实就一个对象.相当于服务器就new了一个Servlet, 这个时候你多个线程同时访问这个对象并且同时修改这个对象的同一个属性的时候就会造成这个问题.
      

  6.   

    我始终有点不理解,我知道PrintWrite对象作为成员变量是线程不安全的,但为什么浏览器a没打印任何东西呢?
      

  7.   

    因为你2次打印的时候使用的PrintWriter都不是A的PrinterWriter
      

  8.   

    打个比方, 你去ktv唱歌, 谁拿到话筒谁唱对吧? 在这个代码片段里面就相当于本来A拿到了话筒准备唱了. 结果B把话筒抢过去了.所以后面两首歌都是B在唱.A么就只能在旁边听着了.