put()后Hashtable仍为空

时间:2013-06-28 14:30:29

标签: java multithreading hashtable

我在这堂课中使用Hastable时遇到了麻烦:

public class HttpBuilder {
    ...        
    private int ret;
    public Hashtable headers;
    private String content;

    HttpBuilder(int majorv, int minorv, int ret){
        ver[0] = majorv;
        ver[1] = minorv;
        this.ret = ret;
        headers = new Hashtable();
    }

    ...
    public void addHeader(String header, String value){
        headers.put(header, value);
    }

    ...
}

此类根据多个输入参数构建字符串。我在多个线程中使用它。像这样:

HttpBuilder Get(HttpParser request) {
    HttpBuilder response;
    String doc;
    if (request.getRequestURL().equals("/")) {
        try {
            doc = LoadDoc("main.html");
        } catch (IOException e) {
            response = new HttpBuilder(1, 1, 500);
            return response;
        }
        response = new HttpBuilder(1, 1, 200);
        response.addHeader("content-type", "text/html");
        response.setContent(doc);
    } else {
        response = new HttpBuilder(1, 1, 404);
    }
    return response;
}

addHeader Hashtable为空后。 消费数据:

public String toString() {
        String result;
        int len = 0;
        result = "HTTP/"+Integer.toString(ver[0])+"."+Integer.toString(ver[1])+
                " "+getHttpReply(ret)+"\n";
        if(content!=null){
            len = content.length();
            if(len!=0){
                headers.put("content-length", Integer.toString(len));
            }
        }

        Iterator it = headers.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry pairs = (Map.Entry) it.next();
            result += pairs.getKey() + ": " + pairs.getValue() + "\n";
            it.remove();
        }

        if(len!=0){
            result+="\n"+content;
        }


        return result;
    }

我使用HttpBuilder的线程类

class ClientThread implements Runnable {
    private Socket socket;
    private ServerData data;
    static public final String NotImplemented = "HTTP/1.1 501 Not Implemented";
    static public final String NotFound = "HTTP/1.1 404 Not Found";

    ClientThread(Socket socket, ServerData data) {
        this.socket = socket;
        this.data = data;
    }

    @Override
    public void run() {
        try {
            HttpParser request = new HttpParser(socket.getInputStream());
            HttpBuilder response;
            if (request.parseRequest() != 200) {
                response = new HttpBuilder(1, 1, 501);
            } else {
                if (request.getMethod().equals("GET")) {
                    response = Get(request);
                } else if (request.getMethod().equals("POST")) {
                    response = Post(request);
                } else {
                    response = new HttpBuilder(1, 1, 400);
                }
            }
        } catch (IOException e) {
            Server.log.log(Level.SEVERE, e.getLocalizedMessage());
        } finally {
            try {
                socket.close();
                Server.log.log(Level.INFO, "Close connection");
            } catch (IOException e) {
                Server.log.log(Level.SEVERE, e.getLocalizedMessage());
            }
        }
    }

    void send(String response) throws IOException {
        PrintWriter out;
        out = new PrintWriter(socket.getOutputStream(), true);
        out.print(response);

    }

    String LoadDoc(String doc) throws IOException {
        final String Folder = "web" + File.separator;
        String result = null;
        doc = Folder + doc;
        long len;
        File f = new File(doc);
        FileReader fr = new FileReader(f);
        len = f.length();
        char[] buffer = new char[(int) len];
        fr.read(buffer);
        result = new String(buffer);
        fr.close();
        return result;

    }

    HttpBuilder Get(HttpParser request) {
        HttpBuilder response;
        String doc;
        if (request.getRequestURL().equals("/")) {
            try {
                doc = LoadDoc("main.html");
            } catch (IOException e) {
                response = new HttpBuilder(1, 1, 500);
                return response;
            }
            response = new HttpBuilder(1, 1, 200);
            response.addHeader("content-type", "text/html");
            response.setContent(doc);
        } else {
            response = new HttpBuilder(1, 1, 404);
        }
        return response;
    }

    HttpBuilder Post(HttpParser request) {
        HttpBuilder response;
        String str;
        if(request.getRequestURL().equals("/")){
            response = new HttpBuilder(1,1, 200);
            str = request.getContentParam("user");
            response.setContent(str+" added to the base.");
        }else {
            response = new HttpBuilder(1, 1, 404);
        }
        return response;
    }    

}

2 个答案:

答案 0 :(得分:1)

toString()中修改对象似乎是一个坏主意。 toString()的目的是返回对象的String表示形式。对toString()的多次后续调用应返回相同的结果。

当您遍历toString()中的标题时,请删除标题:

    Iterator it = headers.entrySet().iterator();
    while (it.hasNext()) {
        Map.Entry pairs = (Map.Entry) it.next();
        result += pairs.getKey() + ": " + pairs.getValue() + "\n";
        it.remove();
    }

如果这是一个理想的行为,我建议您使用一个具有不同名称的方法来实现此逻辑。

由于toString()会覆盖Object的方法,因此可能会将其调用到您不希望调用它的地方,并清空标题地图。

答案 1 :(得分:0)

您的调试器在toString上调用Hashtable,因此您会看到显示的值。但是调用此方法也会删除值,因此在调试器中查看它实际上会清空表。这是一个坏主意,您的toString方法不应该修改对象。

您的HttpBuilder不是线程安全的,因为您使用了Hashtable。幸运的是,你不是从多个线程调用它,至少不是在你发布的代码中。