Mah*_*leh 23 java multithreading tomcat spring-boot
我正在使用springboot 1.5.9.RELEASE + Java 8 + tomcat 9 + Jersey + Oracle和我的应用程序已安排的方法定义如下:
@Configuration
@EnableScheduling
public class ScheduleConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(taskExecutor());
}
@Bean(destroyMethod = "shutdown")
public Executor taskExecutor() {
return Executors.newScheduledThreadPool(100);
}
}
Run Code Online (Sandbox Code Playgroud)
工作班:
@Component
public class ClearCacheJob {
@Scheduled(fixedRate = 3600000, initialDelay = 10000)
public void clearErrorCodesCache() {
try {
logger.info("######## ClearCacheJob #########");
} catch (Exception e) {
logger.error("Exception in ClearCacheJob", e);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我也有一个类来取消注册oracle驱动程序,如下所示:
@WebListener
public class ContainerContextClosedHandler implements ServletContextListener {
private static final Logger logger = LoggerFactory.getLogger(ContainerContextClosedHandler.class);
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
logger.info("######### contextInitialized #########");
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
logger.info("######### contextDestroyed #########");
Enumeration<Driver> drivers = DriverManager.getDrivers();
while (drivers.hasMoreElements()) {
Driver driver = drivers.nextElement();
try {
DriverManager.deregisterDriver(driver);
logger.info(String.format("deregistering jdbc driver: %s", driver));
} catch (SQLException e) {
logger.info(String.format("Error deregistering driver %s", driver), e);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是当停止tomcat时,我收到以下错误:
WARNING [Thread-11] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [hai]
appears to have started a thread named [Timer-0] but has failed to stop it.
This is very likely to create a memory leak. Stack trace of thread:
java.lang.Object.wait(Native Method)
java.lang.Object.wait(Unknown Source)
java.util.TimerThread.mainLoop(Unknown Source)
java.util.TimerThread.run(Unknown Source)
Run Code Online (Sandbox Code Playgroud)
请告知我为什么会收到此错误以及如何解决此问题,谢谢.
我想与此问题的根本原因分析分享一些解决方案。
对于 Oracle 用户:
解决方案#1:
您应该从 Tomcat 的/lib
文件夹中删除您的 Oracle 驱动程序。我遇到了同样的问题,它得到了解决。
注意:让 oracle 驱动程序在/WEB-INF/lib
文件夹中。
解决方案#2:
您可以通过休眠线程使用真正的 hack。
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
logger.info("######### contextDestroyed #########");
Enumeration<Driver> drivers = DriverManager.getDrivers();
while (drivers.hasMoreElements()) {
Driver driver = drivers.nextElement();
try {
DriverManager.deregisterDriver(driver);
logger.info(String.format("deregistering jdbc driver: %s", driver));
} catch (SQLException e) {
logger.info(String.format("Error deregistering driver %s", driver), e);
}
}
try { Thread.sleep(2000L); } catch (Exception e) {} // Use this thread sleep
}
Run Code Online (Sandbox Code Playgroud)
资源链接: “Tomcat无法停止[Abandoned connection cleanup thread]”的解决方法
解决方案#3:
Svetlin Zarev说没有什么可担心的。这是tomcat的标准消息。他给出了如下根本原因分析:
当应用程序已启动 ScheduledExecutor(但任何其他线程/TheadPool 都会发生这种情况)并且没有在 contextDestroyed 时将其关闭时,就会发生此问题。因此,请检查您是否在应用程序/服务器停止时关闭线程。
资源链接: Tomcat8内存泄漏
解决方案#4:
对于Oracle用户,这篇文章有多个答案:为了防止内存泄漏,JDBC驱动程序已被强行注销
解决方案#5:
带解决方案的根本原因分析:
NonRegisteringDriver类中废弃连接的清理线程 被重构为具有静态关闭方法。内存已分配但从未释放。如果您遇到此泄漏问题,
AbandonedConnectionCleanupThread.shutdown()
请使用contextDestroyed
方法中的调用在您的应用程序中实现上下文侦听器。此问题在 Tomcat 应用程序服务器下运行的应用程序中发现,但它可能也适用于其他应用程序服务器。
例如:
Run Code Online (Sandbox Code Playgroud)@WebListener public class YourThreadsListener implements ServletContextListener { public void contextDestroyed(ServletContextEvent arg0) { try { AbandonedConnectionCleanupThread.shutdown(); } catch (InterruptedException e) { } } ... }
请注意,如果容器不支持注释,则将描述添加到 web.xml:
Run Code Online (Sandbox Code Playgroud)<listener> <listener-class>user.package.YourThreadsListener</listener-class> </listener>
资源链接: https : //docs.oracle.com/cd/E17952_01/connector-j-relnotes-en/news-5-1-23.html
更改您ScheduleConfig
的使用shutdownNow
而不是shutdown
破坏方法.
@Configuration
@EnableScheduling
public class ScheduleConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(taskExecutor());
}
@Bean(destroyMethod = "shutdownNow")
public Executor taskExecutor() {
return Executors.newScheduledThreadPool(100);
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
30437 次 |
最近记录: |