Multithreading 如何在部署web应用程序时在启动时运行耗时的任务
我们在服务器启动或应用程序部署时初始化缓存时遇到问题。初始化缓存涉及Multithreading 如何在部署web应用程序时在启动时运行耗时的任务,multithreading,jakarta-ee,webserver,Multithreading,Jakarta Ee,Webserver,我们在服务器启动或应用程序部署时初始化缓存时遇到问题。初始化缓存涉及 查询数据库以获取项目列表 对每个项目进行rmi呼叫 侦听JMS队列/主题上的数据 构建缓存 此初始化过程在启动代码中。所有这些都需要花费大量时间,因此部署需要花费大量时间,或者服务器启动时间正在增加 所以我建议在启动时创建一个线程,并在其中运行初始化代码。我编写了一个示例应用程序来演示它 它涉及一个ServletContextListener,一个过滤器。在侦听器中,我正在创建一个新线程,HeavyProcess将在其中运行。
如果这不好,那么最好的方法是什么?一般来说,在JavaEE环境中创建非托管线程是个坏主意。您将在非托管线程中释放容器管理的事务、用户上下文和更多JavaEE概念。此外,如果线程处理不适当,非托管线程可能会在关闭时阻止conainer 您使用的是哪个JavaEE版本?也许您可以使用Servlet3.0的异步特性
或者调用异步EJB来在启动时完成繁重的工作(@PostConstruct)。然后,调用将在其任务完成时设置一个标志 如果可以使用托管线程,请避免使用非托管线程。如果未正确终止非托管线程和非托管线程的重新部署,则容器无法控制这些线程和非托管线程。因此,您必须注册非托管线程,并以某种方式终止这些线程(这也不容易,因为您必须小心地处理争用条件)
因此,一种解决方案是使用
@Startup
,以及类似以下内容:
@Schedule(second = "*/45", minute = "*", hour = "*")
protected void asyncInit(final Timer timer) {
timer.cancel();
// Do init here
// Set flag that init has been completed
}
我在这里了解了这种方法:
因此,这将为您提供一个异步托管线程,部署不会因@PostConstruct
而延迟。注意计时器。取消()
看看您的实际问题:我建议使用支持“热启动”的缓存 例如,Infinispan支持缓存存储,以便缓存内容在重新启动后仍然有效。如果您有一个集群,那么也有分布式或复制的缓存模式 JBoss7嵌入了Infinispan(它是同一JVM中的集成服务),但也可以独立操作
另一个候选者是Redis(以及任何其他具有持久性的键/值存储也可以)。请澄清:只允许servlet容器或EJB的解决方案?哪个应用服务器(包括版本)?我们使用的是EJB3.0和Glassfish 3.1.2.2应用服务器。我们目前正在使用@Startup注释,这推迟了部署。我使用ServletAPI给出了上述解决方案。为什么创建非托管线程是个坏主意?我的一个大学高年级学生也说了同样的话,但他的回答没有说服力。我想知道。我们正在使用JavaEE6。我将阅读异步EJB并检查它如何适合我们的问题。谢谢。请再看一遍答案。我修改了为什么非托管线程不好的解释。嗨,谢谢你的帮助。基本上,我使用了一个无状态ejb,并用
@Startup
对其进行了注释,这是@Schedule
的方法之一。初始化完成后,我将触发一个事件,过滤器将侦听该事件并设置一个允许请求继续的标志。现在开始工作了。