【问题标题】:Outputstream between threads线程间的输出流
【发布时间】:2014-02-20 16:17:33
【问题描述】:

我的 servlet 上有一个 ajax 方法,可以同时为同一个用户运行。抱歉,如果我用错误的词来描述问题,但到目前为止我是这样理解的(对线程了解不多)。

方法如下

private void ajaxPartidas() throws ServletException, IOException {
    //Variables necesarias
    DataSource pool = (DataSource) session.get().getAttribute("pool");
    Recibo registro = null;

    int id = -1; 
    try{ id = Integer.parseInt(request.get().getParameter("id"));}catch(NumberFormatException e){}

    if(id > 0){
        registro = new Recibo(id);
        if(!registro.obtener(pool))
            registro = null;
        registro.setPartidas(Partida.obtenerRegistros(pool, registro.getId()));
    }

    response.get().setContentType("application/json");
    response.get().setHeader("Content-Type", "application/json; charset=utf-8");        
    response.get().getWriter().print((new Gson()).toJson(registro.getPartidas()));
}   

这个方法是通过 ajax 调用的,它在第一次被调用时工作正常,但第二次(在相同的 id 上)它在 getWriter() 行上返回一个 NullPointer。我环顾四周,每个人似乎都将问题归咎于线程。现在更多的上下文将是每次 servlet 进入

doPost(request, response)

我在全局变量中分配了一个这样声明的线程局部变量

private static ThreadLocal<HttpServletResponse> response = new ThreadLocal<>(); 

我给它分配响应

Home.response.set(response);

在 doPost() 方法中。

如何让 getWriter() 线程安全?

【问题讨论】:

    标签: java ajax multithreading servlets


    【解决方案1】:

    不确定为什么要将响应分配给班级级别ThreadLocal?每个新用户生成的请求都有一个干净的requestresponse 对象。 getWriter 和 servlet 类上的所有方法都是线程安全的,只要您遵循使用 Java Servlet 的正确指南。 Java Servlet 的一般规则是,只要您不使用类级别的变量,您就是线程安全的。

    您需要将请求和响应对象作为参数传递给您的ajaxPartidas 方法,然后像往常一样调用它,而不是使用ThreadLocal。所以你的doPost 方法看起来像这样

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            ajaxPartidas(request, response);
    
    }
    

    并发问题已经由 Servlet 类自己处理了,你只需要编写业务逻辑。有关将 Java Servlet 与 Ajax 结合使用的更多详细信息,请参阅类似线程中的此答案:https://stackoverflow.com/a/4113258/772385

    【讨论】:

    • 我确实使用了类级别的变量,并且曾经遇到过问题(它有来自另一个请求的消息,不知道这是否是该问题的真正根源),但我猜我应该更多地研究何时使用 threadlocal(也许我不需要它们)。
    • 在这种情况下,我认为您不需要它。 servlet API 旨在让您不必进行自己的同步/线程控制,除非您遇到非常奇怪的情况
    【解决方案2】:

    Tomcat 为每个用户请求创建一个新的请求和响应。所以它们已经是线程安全的(除非你进去创建一个新线程)。此外,请确保您正在传递“id”并且设置正确。我认为这是导致 NullPointerException 的与 getWriter() 位于同一行的“registro”对象。

    【讨论】:

    • 我很确定它有 id 并且“registro”不为空,因为它在第一次尝试时工作,然后第二次抛出 NullPointerException。
    猜你喜欢
    • 2013-10-18
    • 1970-01-01
    • 1970-01-01
    • 2015-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-17
    • 1970-01-01
    相关资源
    最近更新 更多