我们有一些生产代码可以有效地执行此代码的操作:
这工作正常,但我注意到一些令人担忧的行为。
当请求一个 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 是什么。
有没有人遇到过这个问题,并且能够为它创建解决方法?
最佳答案
这听起来像是一些请求范围的变量被声明为 servlet 的实例变量。换句话说,代码不是线程安全的。在 web 应用程序的生命周期中只有一个 servlet 实例。它在所有请求之间同时共享。每个请求都算作一个单独的线程。想象一下,您将变量 X(例如图像)声明为 servlet 的实例变量并将其设置在线程 A(请求 A)中,然后在处理过程中线程 B 将使用相同的 servlet 并覆盖变量 X。这将导致线程 A 出现问题因为变量在处理到输出的过程中发生了变化。
因此,永远不要将请求或 session 范围的变量分配为 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 的方法 block 中声明它们)是有道理的) 以避免它们在所有线程(请求)之间共享。
关于java - 使用 Java2D 和 ServletOutputStream 不可预测?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2337919/