1

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.

アプリケーションは DataSource のマップを維持し、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()
    {
        ...
    }

    ....
}

DataSource は、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も、タイマー スレッドが開いたままになっています。の最後にログ ステートメントを追加しcontextDestroyed()、DataSource を閉じて渡されることを確認しました。

また、MySQL ドライバーが WAR ではなく Tomcat の lib にあることも確認しました。

4

1 に答える 1

0

まず第一に、Tomcat がこれについてできることは何もありません。Java SE を使用して Executor を作成しています。したがって、アプリケーション サーバー (Java EE) は、Java SE から直接作成したこの ExecutorService を管理することはできませんし、管理するべきではありません。Java EE ExecutorService を使用するManagedScheduledExecutorService場合は、アプリ サーバーのスレッド プールを使用するため、シャットダウンを気にする必要がないものを使用することを検討してください。それはさておき、質問に...

shutdownNow()をシャットダウンする「すばやく汚い」方法を使用していExecutorServiceます。アプリを穏やかにダウンさせたい場合は、代わりExecutorService.shutdown()に と組み合わせて使用​​することをお勧めしExecutorService.awaitTermination()ます。

ドキュメントによると、shutdownNow()実際に停止できるものについては保証されません。

このメソッドは、アクティブに実行中のタスクが終了するのを待ちません。
...アクティブに実行中のタスクの処理を停止するため
の最善の試みを超える保証はありません。

タスクが停止するのを待ちたい場合は、 を使用する必要がありますawaitTermination()。唯一のことshutdown()またはshutdownNow()できることは callinterrupt()です。これにより、実際にスレッドが停止する場合と停止しない場合があります。終了を待つには、次のようにします。

executor.shutdown(); // or shutdownNow()
if (!executor.isTerminated())
    executor.awaitTermination(10, TimeUnit.SECONDS); // wait for up to 10s
于 2015-12-10T00:12:07.320 に答える