Java 创建部署在Tomcat中的Webapplication线程

Java 创建部署在Tomcat中的Webapplication线程,java,multithreading,spring,web-applications,tomcat,Java,Multithreading,Spring,Web Applications,Tomcat,我正在开发一个部署在Tomcat中的web应用程序。我们在客户端使用Spring、Hibernate和GWT) 此应用程序的功能之一是在创建、更新或删除任何实体时向用户发送警报(电子邮件)。(用户可以动态添加警报,因此需要进行一些处理,以决定应通过电子邮件通知哪些用户) 理想情况下,警报机制应该是异步的,并且应该影响CRUD操作的性能 我想到的第一件事是创建一个线程和一个阻塞队列。线程不断轮询阻塞队列以查看它是否有任何事件。但在web应用程序中创建线程是许多容器所不鼓励的 有人能提出建议吗?这是

我正在开发一个部署在Tomcat中的web应用程序。我们在客户端使用Spring、Hibernate和GWT)

此应用程序的功能之一是在创建、更新或删除任何实体时向用户发送警报(电子邮件)。(用户可以动态添加警报,因此需要进行一些处理,以决定应通过电子邮件通知哪些用户)

理想情况下,警报机制应该是异步的,并且应该影响CRUD操作的性能

我想到的第一件事是创建一个线程和一个阻塞队列。线程不断轮询阻塞队列以查看它是否有任何事件。但在web应用程序中创建线程是许多容器所不鼓励的

有人能提出建议吗?这是正确的做法吗?或者有更好的方法做同样的事情

任何指点都将不胜感激

提前感谢,,
Sachin

您可以使用调度程序定期运行作业,或者使用Spring等效的消息驱动bean(),它由为您执行队列轮询的容器执行。

在容器中创建线程的限制实际上只是一个建议,以防止没有经验的开发人员自取灭亡。实际上,没有容器禁止您这样做。对于java.util.concurrent类,创建线程应该不太容易出错,我也不太担心这个限制

如果您的需求很简单,那么只需在ServletContextListener中创建一个线程/runnable就很容易了。在
contextInitialized()
中创建并启动线程,并在
contextdestromed()
中关闭它。使用由执行者创建的
ScheduledExecutorService
。newSingleThreadScheduledExecutor()。传递给执行器的Runnable将从BlockingQueue读取


如果您的需求发生变化,并且需要更复杂的东西,您可能希望查看JMS/MDB或Quartz之类的调度器。

有很多方法可以做到这一点,最简单的方法(除了简单地创建非托管线程)是使用。当然,您可以使用简单的线程路由,但它在您操作的环境中确实存在缺点(如链接中所述)。

您可以尝试使用Spring 3.x异步方法调用。调用方方法将立即返回,实际执行将异步进行

应用程序上下文:

<task:annotation-driven executor="asyncExecutor" mode="aspectj"/>
<task:executor id="asyncExecutor" pool-size="${executor.poolSize}"/>

有关更多详细信息,请参阅Spring文档:

感谢Thomas的快速回复。我们正在考虑使用AOP,并在成功完成后拦截ArrayBlockingQueue中的所有服务级别CRUD调用和更新。如果我使用调度器,那么拦截所有服务级别CRUD调用的方面将如何通知调度器?你能提供一些关于MDB的Spring等价物的更多细节(链接等)吗。再次感谢好吧,我已经添加了一个链接,你查过了吗?至于调度程序,它应该定期运行(比如每隔1分钟左右),检查等待的警报并发送这些警报。一个这样的调度程序就是。是的,我确实看过链接。只是别忘了将你的线程标记为守护进程线程,这样它们就不会阻止Tomcat完全关闭。这不仅仅是对没有经验的开发人员的建议。关键是不鼓励在设计用于管理资源的环境中使用非托管资源。在web容器中是允许的,但是有一些方法可以提供托管线程,在这种环境中工作得更好。作为旁注,EJB容器甚至不允许这样做。请看这个例子:我不同意这个答案,正如前面提到的EJB容器不允许这样做。如果您使用Google App Engine,它们也会限制异步处理。当您创建自己的线程时,没有对它们的管理。如果您将异步服务分开,就不必担心它会将容器一起拆下。
@Async
public void sendEmail(...) {
 // ...
}