阅读了很多不同的东西,而不是完全熟悉其中某些东西的正确术语,我想知道在tomcat启动时创建线程的正确方法是什么 特定目的。我正在使用Linux系统。
我不是试图从servlet创建一个线程,我很清楚为什么这是坏的。当tomcat启动时,我想要两个具有不同目的的不同线程。第一个线程在每30分钟的一段时间内运行,以审计后端数据。第二个线程负责发送电子邮件。当请求运行必须发送电子邮件的servlet时,我不想等待发送电子邮件的servlet,而是要向此电子邮件线程发送请求并继续。因此,一个定期运行,一个按需运行。我永远不需要增加执行这些任务的线程数量,我只需要这两个,并且只要webapp正在运行就行,并且如果webapp必须停止,我真的不在乎关于优雅的关闭。
我知道我可以采取一些方法:
创建一个在tomcat外部运行 的进程,并定义一种从我的servlet与该进程通信的方法。如果可能的话,我想避免这种情况,因为我希望这两个线程首先直接关联启动和关闭webapp,并让他们能够访问{ {1}},并且不必通过通信渠道提供ser / des数据。
在我的一个servlet的ServletContext
方法中生成两个线程。这看起来很肮脏和苛刻,但它肯定会完成工作。
创建扩展init
或其他ServletContextListener
的{{1}}。这似乎很有吸引力和正确,我想我可以做一个2线程的固定线程池,因为我不再需要了。但这是我尝试做的推荐方法吗?我知道ThreadPoolExecutor
实际上更适合于动态执行ExexutorService
,而不必浪费创建线程的开销。我不知道这是否完全正确,但如果确实如此,我不会将执行人用于其目的。
也许还有更多我不了解的方法,或者正确的方法来实现上述方法之一。
答案 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的启动和/或关闭。