在启动时在tomcat中创建任务线程的正确方法

时间:2014-09-29 13:39:58

标签: java tomcat servlets threadpool

阅读了很多不同的东西,而不是完全熟悉其中某些东西的正确术语,我想知道在tomcat启动时创建线程的正确方法是什么 特定目的。我正在使用Linux系统。

我不是试图从servlet创建一个线程,我很清楚为什么这是坏的。当tomcat启动时,我想要两个具有不同目的的不同线程。第一个线程在每30分钟的一段时间内运行,以审计后端数据。第二个线程负责发送电子邮件。当请求运行必须发送电子邮件的servlet时,我不想等待发送电子邮件的servlet,而是要向此电子邮件线程发送请求并继续。因此,一个定期运行,一个按需运行。我永远不需要增加执行这些任务的线程数量,我只需要这两个,并且只要webapp正在运行就行,并且如果webapp必须停止,我真的不在乎关于优雅的关闭。

我知道我可以采取一些方法:

  1. 创建一个在tomcat外部运行 的进程,并定义一种从我的servlet与该进程通信的方法。如果可能的话,我想避免这种情况,因为我希望这两个线程首先直接关联启动和关闭webapp,并让他们能够访问{ {1}},并且不必通过通信渠道提供ser / des数据。

  2. 在我的一个servlet的ServletContext方法中生成两个线程。这看起来很肮脏和苛刻,但它肯定会完成工作。

  3. 创建扩展init或其他ServletContextListener的{​​{1}}。这似乎很有吸引力和正确,我想我可以做一个2线程的固定线程池,因为我不再需要了。但这是我尝试做的推荐方法吗?我知道ThreadPoolExecutor实际上更适合于动态执行ExexutorService,而不必浪费创建线程的开销。我不知道这是否完全正确,但如果确实如此,我不会将执行人用于其目的。

  4. 也许还有更多我不了解的方法,或者正确的方法来实现上述方法之一。

2 个答案:

答案 0 :(得分:1)

请参阅以下Q& A:tomcat 6 thread pool for asynchronous processing

此外,您可能需要Executors.newFixedThreadPool而不是Executors.newScheduledThreadPool来创建能够执行重复任务的ScheduledExecutorService实例。

希望这会有所帮助......

答案 1 :(得分:1)

我不会继续实现线程池本身,但问题是:

  

启动

中在tomcat中创建任务线程的正确方法

正如其他人所说,你的第三种方法几乎是正确的但是这取决于你的服务结构。

我会给你一个例子,然后解释一下:

public class YourServletContextListener implements ServletContextListener{     
    @Override
    public void contextDestroyed(ServletContextEvent sce) {

    }         
    @Override
    public void contextInitialized(ServletContextEvent sce) {

    }
}

来自文档:

contextInitialized:
  

所有ServletContextListener都会收到上下文初始化的通知   在初始化Web应用程序中的任何过滤器或servlet之前

如果我理解你的方法正确,那么我会问你:你想如何启动服务或向仍未初始化的servlet发送任何请求?

如果您想要启动的服务不直接与Web应用程序通信/需要任何servlet或过滤器或任何数据,这将起作用。之后,在启动容器后,他们可以确保彼此通信。

正如我之前所说,哪种方式最好使用取决于服务结构/逻辑。

另一种方法可能是使用过滤器:

void init(FilterConfig filterConfig) throws ServletException
  

由Web容器调用以向过滤器指示它正在进行   投入使用。 servlet容器调用init方法   在实例化过滤器后恰好一次。

void destroy()
  

由Web容器调用以向过滤器指示它正在进行   停止服务。此方法仅在所有线程中调用一次   在过滤器的doFilter方法中已经退出或超时后   期过了。在Web容器调用此方法之后,它将会   不要在这个过滤器实例上再次调用doFilter方法。

     

此方法为过滤器提供了清理任何资源的机会   被保留(例如,内存,文件句柄,线程)和   确保任何持久状态与过滤器同步   记忆中的当前状态。

但过滤器不适用于此类方法!

  

如果要拦截加工a的HTTP请求,请使用过滤器   特定的URL模式,因为您要检查/修改HTTP   请求/响应。如果需要,请使用ServletContextListener   拦截webapp的启动和/或关闭。