在注销jdbc驱动程序后停止/中断线程

博格丹·科曼(Bogdan Coman)

我想在注销jdbc驱动程序后通过调用方法来关闭线程。

public class CleanupContextListener implements ServletContextListener{
    boolean driverDeregisterFlag = false;

        public void contextInitialized(ServletContextEvent servletContextEvent) {
            //To change body of implemented methods use File | Settings | File Templates.
        }

        public void contextDestroyed(ServletContextEvent servletContextEvent) {
            Enumeration<Driver> drivers = DriverManager.getDrivers();
            while(drivers.hasMoreElements()) {
                Driver driver = drivers.nextElement();
                ClassLoader driverClassLoader = driver.getClass().getClassLoader();
                ClassLoader thisClassLoader = this.getClass().getClassLoader();
                if (driverClassLoader != null && thisClassLoader != null && driverClassLoader.equals(thisClassLoader)) {
                   try {
                       DriverManager.deregisterDriver(driver);
                       driverDeregisterFlag = true;
                   } catch (SQLException e) {
                       e.printStackTrace();
                   }
                }
            }
            if (driverDeregisterFlag) {
                ConfigManager.stopCurrentThread();    
            }
        }
    }

如您所见,我正在尝试调用ConfigManager.stopCurrentThread()并停止当前线程。ConfigManager是实现Runnable的类。stopCurrentThread()在ConfigManager中定义为空方法。
我想在stopCurrentThread()中放入一些代码,然后关闭ConfigManager中的线程。

我怎样才能做到这一点?

瓜拉塔米达

这是我的代码的片段,正在解决类似的问题。在c3p0 pool + tomcat 8上进行了测试,但是您可能可以根据需要对其进行修改。

/**
 * Destroying application context. We need to safely stop exporting thread
 * and do cleanup.
 * 
 * @param arg0
 *            reason for cleanup
 */
@Override
public void contextDestroyed(@NotNull ServletContextEvent arg0) {

    // Safely stop exporting service and shut down the application context
    super.contextDestroyed(arg0);

    // Close all JDBC connections
    C3P0Registry.getNumPooledDataSources();
    Iterator<?> it = C3P0Registry.getPooledDataSources().iterator();
    while (it.hasNext()) {
        try {
            PooledDataSource dataSource = (PooledDataSource) it.next();
            dataSource.close();
        } catch (Exception e) {
            log.error("Error when closing connections ...", e);
        }
    }

    // This manually unregisters JDBC drivers, which prevents Tomcat 7 from
    // complaining about memory leaks with this class
    Enumeration<Driver> drivers = DriverManager.getDrivers();
    while (drivers.hasMoreElements()) {
        Driver driver = drivers.nextElement();
        try {
            DriverManager.deregisterDriver(driver);
            log.info(String.format("Unregistering jdbc driver: %s", driver));
        } catch (SQLException e) {
            log.error(
                    String.format("Error deregistering driver %s", driver),
                    e);
        }
    }

    // Waiting for daemon close() c3p0 jdbc pool thread
    Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
    for (Thread th : threadSet) {
        if (th.isDaemon()) {
            try {
                if (th.getName().equals(
                        "Resource Destroyer in BasicResourcePool.close()")) {
                    th.join();
                }
            } catch (Exception ex) {
                log.info("Shutdown waiting was interrupted ...");
            }
        }
    }
    // Clear all thread local variables, this prevents Tomcat 7 from
    // complaining about memory leaks
    immolate();

}

/**
 * Cleanup function which cleans all thread local variables. Using thread
 * local variables is not a good practice but unfortunately some libraries
 * are still using them. We need to clean them up to prevent memory leaks.
 * 
 * @return number of Thread local variables
 */
private int immolate() {
    int count = 0;
    try {
        final Field threadLocalsField = Thread.class
                .getDeclaredField("threadLocals");
        threadLocalsField.setAccessible(true);
        final Field inheritableThreadLocalsField = Thread.class
                .getDeclaredField("inheritableThreadLocals");
        inheritableThreadLocalsField.setAccessible(true);
        for (final Thread thread : Thread.getAllStackTraces().keySet()) {
            count += clear(threadLocalsField.get(thread));
            count += clear(inheritableThreadLocalsField.get(thread));
        }
        log.info("Immolated " + count + " values in ThreadLocals");
    } catch (Exception e) {
        log.error("ThreadLocalImmolater.immolate()", e);
    }
    return count;
}

/**
 * Cleaner for thread local map.
 * 
 * @param threadLocalMap
 *            thread local map to clean or null
 * @return number of cleaned objects
 * @throws Exception
 *             in case of error
 */
private int clear(@NotNull final Object threadLocalMap) throws Exception {
    if (threadLocalMap == null) {
        return 0;
    }
    int count = 0;
    final Field tableField = threadLocalMap.getClass().getDeclaredField(
            "table");
    tableField.setAccessible(true);
    final Object table = tableField.get(threadLocalMap);
    for (int i = 0, length = Array.getLength(table); i < length; ++i) {
        final Object entry = Array.get(table, i);
        if (entry != null) {
            final Object threadLocal = ((WeakReference<?>) entry).get();
            if (threadLocal != null) {
                log(i, threadLocal);
                Array.set(table, i, null);
                ++count;
            }
        }
    }
    return count;
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

Web应用程序[]注册了JDBC驱动程序[com.mysql.jdbc.Driver],但是在Web应用程序停止时未能注销它

来自分类Dev

从自己中断线程

来自分类Dev

中断线程

来自分类Dev

Spring Batch-作业停止时中断线程

来自分类Dev

重启后无线驱动程序停止工作

来自分类Dev

升级nvidia驱动程序12.04后视频停止播放

来自分类Dev

GlassFish为防止内存泄漏,已强制注销JDBC驱动程序

来自分类Dev

打印驱动程序停止

来自分类Dev

无法使nVidia驱动程序与16.04一起使用,请在登录后立即注销

来自分类Dev

无法使nVidia驱动程序与16.04一起使用,请在登录后立即注销

来自分类Dev

设备驱动程序中的中断处理

来自分类Dev

15.10-> 16.04 LTS升级后登录中断,与NVIDIA驱动程序有关

来自分类Dev

15.10-> 16.04 LTS升级后登录中断,与NVIDIA驱动程序有关

来自分类Dev

指定JDBC数据库驱动程序的最大线程数

来自分类Dev

线程interrupt()不中断线程

来自分类Dev

引导程序div中断线

来自分类Dev

JDBC ODBC驱动程序连接

来自分类Dev

安装MySQL JDBC驱动程序msi

来自分类Dev

Maven:Oracle JDBC驱动程序

来自分类Dev

无法注册JDBC驱动程序

来自分类Dev

加载postgreSQL JDBC驱动程序

来自分类Dev

JDBC驱动程序注册死锁?

来自分类Dev

SQL Server 2014的JDBC驱动程序

来自分类Dev

TigerGraph DB的JDBC驱动程序

来自分类Dev

JDBC驱动程序实现如何工作?

来自分类Dev

加载postgreSQL JDBC驱动程序

来自分类Dev

MySQL JDBC驱动程序错误

来自分类Dev

SQL Server 2014的JDBC驱动程序

来自分类Dev

Scala和MySQL JDBC驱动程序