Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 如何在部署web应用程序时在启动时运行耗时的任务_Multithreading_Jakarta Ee_Webserver - Fatal编程技术网

Multithreading 如何在部署web应用程序时在启动时运行耗时的任务

Multithreading 如何在部署web应用程序时在启动时运行耗时的任务,multithreading,jakarta-ee,webserver,Multithreading,Jakarta Ee,Webserver,我们在服务器启动或应用程序部署时初始化缓存时遇到问题。初始化缓存涉及 查询数据库以获取项目列表 对每个项目进行rmi呼叫 侦听JMS队列/主题上的数据 构建缓存 此初始化过程在启动代码中。所有这些都需要花费大量时间,因此部署需要花费大量时间,或者服务器启动时间正在增加 所以我建议在启动时创建一个线程,并在其中运行初始化代码。我编写了一个示例应用程序来演示它 它涉及一个ServletContextListener,一个过滤器。在侦听器中,我正在创建一个新线程,HeavyProcess将在其中运行。

我们在服务器启动或应用程序部署时初始化缓存时遇到问题。初始化缓存涉及

  • 查询数据库以获取项目列表
  • 对每个项目进行rmi呼叫
  • 侦听JMS队列/主题上的数据
  • 构建缓存
  • 此初始化过程在启动代码中。所有这些都需要花费大量时间,因此部署需要花费大量时间,或者服务器启动时间正在增加

    所以我建议在启动时创建一个线程,并在其中运行初始化代码。我编写了一个示例应用程序来演示它

    它涉及一个ServletContextListener,一个过滤器。在侦听器中,我正在创建一个新线程,HeavyProcess将在其中运行。当它完成时,将触发一个事件,过滤器将监听该事件。收到事件后,筛选器将允许传入http请求。在此之前,过滤器将所有客户端重定向到默认页面,该页面显示应用程序正在初始化的消息

    我介绍了这种方法,但很少有人提出担忧

  • 我们不应该理想地创建线程,因为处理线程会很困难
  • 我的问题是为什么我们不能在web应用程序中创建这样的线程


    如果这不好,那么最好的方法是什么?

    一般来说,在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
    的方法之一。初始化完成后,我将触发一个事件,过滤器将侦听该事件并设置一个允许请求继续的标志。现在开始工作了。