【问题标题】:Using Java2D and ServletOutputStream not predictable?使用 Java2D 和 ServletOutputStream 不可预测?
【发布时间】:2010-02-25 21:49:37
【问题描述】:

我们有一些生产代码有效地完成了这段代码的工作:

http://java.sun.com/products/java-media/2D/reference/faqs/index.html#Q_Can_I_use_Java2D_to_generate_d

这很好用,但是我注意到一些令人担忧的行为。

当一个 servlet 被请求并且一些图像数据通过 ServletOutputStream 返回到浏览器时,如果在图像完成自己在屏幕上绘制之前触发另一个请求,这总是会导致整个 Jaguar 服务器崩溃,并出现以下跟踪:

j com.sybase.jaguar.servlet.JaguarConnection.writeClient([BII)V+0 j com.sybase.jaguar.servlet.JagHttp11OutputStream.writeChunk()V+92 j com.sybase.jaguar.servlet.JagHttp11OutputStream.writeOut()V+57 j com.sybase.jaguar.servlet.ResponseImpl.flushBuffer(Z)V+93 j com.sybase.jaguar.servlet.ResponseImpl.flushBuffer()V+17 j com.sybase.jaguar.servlet.JaguarOutputStream.flush()V+19 j javax.imageio.stream.FileCacheImageOutputStream.close()V+50 j javax.imageio.stream.ImageInputStreamImpl.finalize()V+8

我在网上找到了一些参考资料,说我正在尝试做的事情不可靠,即:

http://forums.sun.com/thread.jspa?trange=15&threadID=560000&forumID=20&tstart=0

但是,老实说,我不清楚 EDT 是什么。

有没有人遇到过这个问题,并且能够为它创建一个解决方法?

【问题讨论】:

    标签: java servlets java-2d


    【解决方案1】:

    这听起来像是一些请求范围的变量被声明为 servlet 的 实例变量。换句话说,代码不是线程安全的。在 web 应用程序的生命周期中只有一个 servlet 实例。它在所有请求之间同时共享。每个请求都算作一个单独的线程。假设您将变量 X(例如图像)声明为 servlet 的实例变量并将其设置在线程 A(请求 A)中,然后在处理期间线程 B 将使用相同的 servlet 并覆盖变量 X。这将导致线程 A 出现问题因为变量在处理到输出的过程中发生了变化。

    因此,您永远不应将请求或会话范围的变量分配为 servlet 的实例变量:

    public class ImageServlet extends HttpServlet {
    
        private Image image;
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) {
            this.image = imageDAO.find(request.getPathInfo()); // Not threadsafe!! image is been shared among all requests.
            // ...
        }
    }
    

    不过如此

    public class ImageServlet extends HttpServlet {
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) {
            Image image = imageDAO.find(request.getPathInfo()); // Threadsafe.
            // ...
        }
    }
    

    这样每个线程都有自己的变量。

    也就是说,EDT 是“事件调度线程”。我不做 Swing,所以我不能说太多,但他试图告诉你应该保留所有变量 threadlocal 是有道理的(即在 servlet 的方法块中声明它们) 以避免它们在所有线程(请求)之间共享。

    【讨论】:

      【解决方案2】:

      我至少可以说出它的 EDT:那是 Event Dispatch Thread,所有 AWT 和 Swing 操作完成的线程。
      AFAIK,每个 JVM 只能有一个 EDT,因为这是在屏幕上输出图形的操作。我知道您的操作是无头的,但也许规则仍然适用。
      我不确定正确的解决方法是什么。也许每个请求线程产生一个 JVM?不知道是否实用……

      【讨论】:

        【解决方案3】:

        您的意思是同一浏览器在检索和呈现前一页上的图像之前尝试导航到新 URL?这可能会导致浏览器关闭用于检索图像的网络连接,这取决于 servlet 实现可能会导致捕获和记录异常,尽管不存在真正的错误情况(浏览器只是在 servlet 之前断开连接已完成工作)。

        您在此处发布堆栈跟踪,但 JaguarConnection 类抛出的实际异常是什么?

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-04-13
          • 2018-01-17
          • 1970-01-01
          • 1970-01-01
          • 2021-01-05
          • 2012-07-10
          • 1970-01-01
          相关资源
          最近更新 更多