2

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

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 是什么。

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

4

3 回答 3

1

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

于 2010-02-25T22:40:54.157 回答
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,所以我不能说太多,但他试图告诉你应该将所有变量保持在线程本地(即在 servlet 的方法块中声明它们)以避免它们在它们之间共享是有道理的所有线程(请求)。

于 2010-02-25T23:20:03.593 回答
0

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

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

于 2010-02-25T22:58:02.323 回答