我们有一些生产代码可以有效地执行此代码的操作:
这很好,但是我注意到了一些有关行为。
当请求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是什么。
是否有人遇到此问题,并且能够为其创建解决方法?
答案 0 :(得分:1)
我至少可以说它是什么EDT:那是事件调度线程,即完成所有AWT和Swing操作的线程。
AFAIK,每个JVM只能有一个EDT,因为这是在屏幕上输出图形的操作。我知道你的行动是无头的,但也许规则仍然适用
我不确定正确的解决办法是什么。也许每个请求线程产生一个JVM?不确定它是否实用......
答案 1 :(得分:1)
这听起来有些请求作用域变量已被声明为servlet的实例变量。换句话说,代码不是线程安全的。在webapplication的生命周期中,只有一个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是“Event Dispatcher Thread”。我不做Swing,所以我不能说太多,但是有意义的是他试图告诉你应该保留所有变量 threadlocal (即在servlet的方法块中声明它们全部)避免它们在所有线程(请求)之间共享。
答案 2 :(得分:0)
您是说在检索并呈现上一页上的图像之前,同一浏览器是否尝试导航到新的URL?这可能会导致浏览器关闭用于检索映像的网络连接,这取决于servlet实现可能会导致异常被捕获并记录,尽管不存在真正的错误情况(浏览器只是在servlet之前删除了连接)已经完成了工作。)
您在此处发布堆栈跟踪,但JaguarConnection类抛出的实际异常是什么?