在 HTTP POST(由应用程序生成,而不是由用户生成)之后,我想发送一封电子邮件。我的电子邮件发送过程正确,但我不确定 Java Web 应用程序服务器如何工作。
我特别担心超时,我想知道我是否以某种方式阻塞了一个重要的线程。
如果我执行以下操作:
@Override
public void doPost(
final HttpServletRequest req,
final HttpServletResponse resp
) throws IOException, ServletException {
final PrintWriter pw = resp.getWriter();
pw.write( ... );
pw.flush();
pw.close();
// Here I'm sending an email, this can potentially
// block until the email send procedure times out
// (the timeout is set to 5 seconds)
sendEmail(...);
}
如果电子邮件服务器关闭,线程将阻塞,直到我的 sendEmail 超时(我将超时设置为几秒)。
然后我阻塞了哪个线程?我的意思是,显然我意识到我正在阻塞正在处理此 POST 的线程,但这是否是一个问题?该线程下一步应该做什么?
我读到我不应该从 Java webapp 服务器创建新线程,所以我认为我不应该执行以下操作,对吧?
Thread t = new Thread( new Runnable() {
public void run() {
sendEmail();
}
});
t.start();
请注意,我的问题并非特定于电子邮件发送:我想了解每次您计划在 GET 或 POST 之后执行潜在的阻塞/长时间操作时,在 Java Web 应用程序中必须注意什么。
最佳答案
在 servlet 中启动线程是可以的,您只需要非常小心,以确保它在 servlet 取消部署时终止。
最简单的方法是在 servlet 启动时创建一个 java.util.concurrent.ExecutorService 并在 servlet 销毁时将其关闭。然后,您可以将电子邮件作业提交到执行器服务并从 doPost
返回。请注意,如果 servlet 在作业排队后被销毁,则某些电子邮件可能无法发送。
在代码中:
class EmailServlet extends HttpServlet {
private ExecutorService emailSender;
public void init() {
emailSender = Executors.newFixedThreadPool(1);
}
public void destroy() {
emailSender.shutdownNow();
}
public void doPost(...) {
...
emailSender.execute(new Runnable() {public void run() {sendEmail();}});
}
}
关于java - 如何处理 doGet 或 doPost 中潜在的长时间操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4504773/