gpt4 book ai didi

java - Tomcat + TomcatJDBC ServletContextListener 开启线程

转载 作者:行者123 更新时间:2023-11-28 22:28:02 26 4
gpt4 key购买 nike

从 Tomcat 取消部署应用程序时,有一些线程处于打开状态。

org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/services] appears to have started a thread named [Abandoned connection cleanup thread] but has failed to stop it. This is very likely to create a memory leak.
org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/services] appears to have started a thread named [Timer-0] but has failed to stop it. This is very likely to create a memory leak.

应用程序维护一个 DataSources 映射并运行一个 ScheduledExecutorService 以每 5 分钟更新一次映射。

@WebListener
public class DataSourceFactory implements ServletContextListener
{
private static Map<String, DataSource> rdsDataSourceMap;
private static ScheduledExecutorService scheduler;
private static final long CONNECTION_MAP_REFRESH_INTERVAL = 5;

@Override
public void contextInitialized(ServletContextEvent event)
{
scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(new Runnable(){
@Override
public void run() {
cacheDatasourceMap();
}
}, 0, CONNECTION_MAP_REFRESH_INTERVAL, TimeUnit.MINUTES);
}

@Override
public void contextDestroyed(ServletContextEvent event)
{
scheduler.shutdownNow();
if (localPool != null) {
localPool.close();
}
for (DataSource ds : rdsDataSourceMap.values()) {
if (ds != null) {
ds.close();
}
}
}

private void cacheDatasourceMap()
{
...
}

....
}

数据源是使用 TomcatJDBC 创建的,参数如下:

driver=com.mysql.jdbc.Driver
jmxEnabled=true
testWhileIdle=true
testOnBorrow=true
validationQuery=SELECT 1
testOnReturn=false
validationInterval=30000
timeBetweenEvictionRunsMillis=5000
maxActive=100
maxIdle=20
initialSize=10
maxWait=100000
removeAbandonedTimeout=60
minEvictableIdleTimeMillis=30000
minIdle=10
logAbandoned=true
removeAbandoned=true
jdbcInterceptors=org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer;org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer;org.apache.tomcat.jdbc.pool.interceptor.SlowQueryReportJmx(threshold=10000)

更新

摆脱 ScheduledExecutorService 后,我仍然看到 Timer 线程处于打开状态。我在 contextDestroyed() 的末尾添加了一条日志记录语句,并验证它正在关闭 DataSources。

我还验证了 MySQL 驱动程序在 Tomcat 的库中,而不是在 WAR 中。

最佳答案

首先,Tomcat 对此无能为力,您正在使用 Java SE 创建一个执行器。因此,应用程序服务器(Java EE)不能也不应该管理您直接从 Java SE 创建的 ExecutorService。如果您想使用 Java EE ExecutorService,请考虑使用 ManagedScheduledExecutorService,您无需担心关闭,因为它使用应用服务器的线程池。有了这个问题,问题...

您正在使用 shutdownNow(),这是一种关闭 ExecutorService 的“快速而肮脏”的方式。如果您想轻轻地关闭您的应用程序,我建议您结合使用 ExecutorService.shutdown()ExecutorService.awaitTermination()

根据文档,shutdownNow() 不保证实际可以停止什么。

This method does not wait for actively executing tasks to terminate.
...
There are no guarantees beyond best-effort attempts to stop processing actively executing tasks.

如果你关心等待任务停止,你需要使用awaitTermination()shutdown()shutdownNow() 唯一能做的就是调用 interrupt(),这可能会也可能不会真正停止线程。要等待终止,请执行以下操作:

executor.shutdown(); // or shutdownNow()
if (!executor.isTerminated())
executor.awaitTermination(10, TimeUnit.SECONDS); // wait for up to 10s

关于java - Tomcat + TomcatJDBC ServletContextListener 开启线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34190999/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com