我有两个servlet,如下所示:
public class ServletA extends HttpServlet {
public void doGet(final HttpServletRequest request,
final HttpServletResponse response) {
// Kick off some async processing
RequestQueue.putRequest(new RequestInfo(...), new FutureCallback<ResponseInfo> () {
@Override
public void completed(ResponseInfo responseInfo) {
// Send some data to database
TransactionManager.getInstance().create(...);
}
)};
// Send response to client
response.getWriter().println("ServletA: SUCCESS");
}
}
public class ServletB extends HttpServlet {
public void doGet(final HttpServletRequest request,
final HttpServletResponse response) {
// Use a CountDownLatch to force synchronous processing on an asynchronous construct
final CountDownLatch completedSignal = new CountDownLatch(1);
RequestQueue.putRequest(new RequestInfo(...), new FutureCallback<ResponseInfo> () {
@Override
public void completed(ResponseInfo responseInfo) {
// Send some data to database, and send response to client
TransactionManager.getInstance().create(...);
response.getWriter().println("ServletB: SUCCESS");
completedSignal.countDown();
}
)};
completedSignal.await();
}
}
问题是,在负载很重的情况下,调用ServletA的客户端有时会收到“Servlet B:SUCCESS”作为响应。
为什么会这样?怎么修复?
感谢。
答案 0 :(得分:1)
向ServletB添加AtomicBoolean以确保仅在修复问题后使用响应对象:
public class ServletB extends HttpServlet {
public void doGet(final HttpServletRequest request,
final HttpServletResponse response) {
// Use a CountDownLatch to force synchronous processing on an asynchronous construct
final CountDownLatch completedSignal = new CountDownLatch(1);
// Use an AtomicBoolean to ensure response is only used once
AtomicBoolean responseSent = new AtomicBoolean(false);
RequestQueue.putRequest(new RequestInfo(...), new FutureCallback<ResponseInfo> () {
@Override
public void completed(ResponseInfo responseInfo) {
// Ensure response has not already been sent
if(!responseSent.compareAndSet(false, true)) { return; }
// Send some data to database, and send response to client
TransactionManager.getInstance().create(...);
response.getWriter().println("ServletB: SUCCESS");
completedSignal.countDown();
}
)};
if(!completedSignal.await(60, TimeUnit.SECONDS)) {
// Ensure response has not already been sent
if(responseSent.compareAndSet(false, true)) {
response.sendError(503);
}
}
}
}