6

Java利用ShutDownHook关闭系统资源

 3 years ago
source link: https://www.wencst.com/archives/239
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Java关闭钩子

在Java程序中可以通过添加关闭钩子,实现在程序退出时关闭资源的功能。
使用Runtime.addShutdownHook(Thread hook)向JVM添加关闭钩子

 public void addShutdownHook(Thread hook) {
        SecurityManager sm = System.getSecurityManager(); if (sm != null) {
            sm.checkPermission(new RuntimePermission("shutdownHooks"));
        }
        ApplicationShutdownHooks.add(hook);
    }

ShutdownHook(Thread hook)方法,可以注册一个JVM关闭的钩子,这个钩子可以在以下几种场景被调用:

1)程序正常退出
2)使用System.exit()
3)终端使用Ctrl+C触发的中断
4)系统关闭
5)使用Kill pid命令干掉进程

在Eclipse中使用关闭钩子

在Eclipse中直接点击Terminate关闭程序时不会触发关闭钩子的。在Linux下使用kill -9也是不会触发钩子的

如果想在Eclipse中实现关闭钩子的功能,需要另起一个线程监听控制台,在控制台输入Enter时关闭系统

/**
 * <p>类描述: 输入Enter键关闭系统 </p>
 * <p>创建人:王成委  </p>
 * <p>创建时间:2015年6月8日 下午5:23:31  </p>
 */
public class ExitThread extends Thread {
    private Log logger = LogFactory.getLog(getClass());
    public void run() {
        logger.info("press ENTER to call System.exit(0) "); try {
            System.in.read();
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.exit(0);
    }

}

Spring中关闭资源的配置

在使用Spring时,可以在Bean中配置destroy-method来实现系统关闭时对Bean的一些处理。

<bean id="simpleHandler" class="com.tiamaes.gjds.socket.server.SimpleHanlder"
    destroy-method="destroy">
    <property name="annotationSocketServiceFactory"
        ref="annotationSocketServiceFactory" />
</bean>
//此方法需要声明void,并且没有任何参数
    public void destroy(){
        logger.info("Stop socket handler.");
    }

Java+Spring实现在程序退出时关闭Spring

/**
 * <p>类描述: 系统关闭钩子,用于关闭Spring资源 </p>
 * <p>创建人:王成委  </p>
 * <p>创建时间:2015年6月8日 下午5:06:46  </p>
 */
public class ShutDownHook extends Thread {
    private Log logger = LogFactory.getLog(getClass());
    private ConfigurableApplicationContext applicationContext;
    public ShutDownHook(ConfigurableApplicationContext applicationContext ){
        super();
        this.applicationContext = applicationContext;
    }
    @Override
    public void run() {
        logger.info("Start clean the login info."); //在系统关闭时,清理所有用户的登录状态
        TbDxpUserLoginStatusRepository repository = applicationContext.getBean(TbDxpUserLoginStatusRepository.class);
        repository.deleteAll();
        applicationContext.close();
        logger.info("Socket server shutdown");
    }
}

在ShutdownHook实例化时需要传入Spring上下文,在系统关闭时调用ApplicationContext的Close方法。

    public static void main(String[] args) {
        ClassPathXmlApplicationContext ct = new ClassPathXmlApplicationContext("applicationContext.xml");

        Runtime.getRuntime().addShutdownHook(new ShutDownHook(ct)); //在正式部署时不需要下面的代码,这段代码仅供调试时使用
        Thread thread = new ExitThread();
        thread.start();
    }

最终效果如下

2015-06-09 09:43:51,233 INFO ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@2e52cdcc: startup date [Tue Jun 09 09:43:51 CST 2015]; root of context hierarchy
2015-06-09 09:43:52,263 INFO XmlBeanDefinitionReader  - Loading XML bean definitions from class path resource [applicationContext.xml] 2015-06-09 09:43:55,559 INFO XmlBeanDefinitionReader  - Loading XML bean definitions from class path resource [applicationContext-service.xml] 2015-06-09 09:43:55,724 INFO XmlBeanDefinitionReader  - Loading XML bean definitions from class path resource [applicationContext-db.xml] 2015-06-09 09:44:01,358 INFO PropertyPlaceholderConfigurer  - Loading properties file from class path resource [jdbc.properties] 2015-06-09 09:44:02,687 INFO MLog  - MLog clients using slf4j logging.
2015-06-09 09:44:06,563 INFO C3P0Registry  - Initializing c3p0-0.9.5-pre9 [built 08-October-2014 03:06:08 -0700; debug? true; trace: 10] 2015-06-09 09:44:08,930 INFO LocalContainerEntityManagerFactoryBean  - Building JPA container EntityManagerFactory for persistence unit 'Oracle'
2015-06-09 09:44:09,251 INFO LogHelper  - HHH000204: Processing PersistenceUnitInfo [ name: Oracle ...] 2015-06-09 09:44:13,400 INFO Version  - HHH000412: Hibernate Core {4.3.7.Final}
2015-06-09 09:44:13,404 INFO Environment  - HHH000206: hibernate.properties not found
2015-06-09 09:44:13,439 INFO Environment  - HHH000021: Bytecode provider name : javassist
2015-06-09 09:44:15,016 INFO Version  - HCANN000001: Hibernate Commons Annotations {4.0.5.Final}
2015-06-09 09:44:15,660 INFO Dialect  - HHH000400: Using dialect: org.hibernate.dialect.Oracle10gDialect
2015-06-09 09:44:15,739 INFO LobCreatorBuilder  - HHH000422: Disabling contextual LOB creation as connection was null
2015-06-09 09:44:16,056 INFO ASTQueryTranslatorFactory  - HHH000397: Using ASTQueryTranslatorFactory
2015-06-09 09:44:21,032 INFO EhCacheManagerFactoryBean  - Initializing EhCache CacheManager
2015-06-09 09:44:21,977 INFO ExitThread  - press ENTER to call System.exit(0)

2015-06-09 09:54:23,694 INFO ShutDownHook  - Start clean the login info.
2015-06-09 09:54:23,787 INFO AbstractPoolBackedDataSource  - Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 5, acquireRetryAttempts -> 0, acquireRetryDelay -> 1000, autoCommitOnClose -> true, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 5000, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, contextClassLoaderSource -> caller, dataSourceName -> 1hge7dt991ndh1jygiycad|7402fff0, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> oracle.jdbc.OracleDriver, extensions -> {}, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, forceUseNamedDriverClass -> false, identityToken -> 1hge7dt991ndh1jygiycad|7402fff0, idleConnectionTestPeriod -> 0, initialPoolSize -> 5, jdbcUrl -> jdbc:oracle:thin:@192.168.57.62:1521:orcl, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 36000, maxIdleTimeExcessConnections -> 1800, maxPoolSize -> 20, maxStatements -> 0, maxStatementsPerConnection -> 0, minPoolSize -> 5, numHelperThreads -> 3, preferredTestQuery -> null, privilegeSpawnedThreads -> false, properties -> {user=******, password=******}, propertyCycle -> 0, statementCacheNumDeferredCloseThreads -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, userOverrides -> {}, usesTraditionalReflectiveProxies -> false ] Hibernate: select tbdxpuserl0_.SESSION_ID as SESSION_ID1_1_, tbdxpuserl0_.CREATE_TIME as CREATE_TIME2_1_, tbdxpuserl0_.IP_ADDR as IP_ADDR3_1_, tbdxpuserl0_.LOGIN_TIME as LOGIN_TIME4_1_, tbdxpuserl0_.status as status5_1_, tbdxpuserl0_.USER_ID as USER_ID6_1_, tbdxpuserl0_.username as username7_1_ from TB_DXP_USER_LOGIN_STATUS tbdxpuserl0_
2015-06-09 09:54:25,555 INFO ClassPathXmlApplicationContext  - Closing org.springframework.context.support.ClassPathXmlApplicationContext@2e52cdcc: startup date [Tue Jun 09 09:43:51 CST 2015]; root of context hierarchy
2015-06-09 09:54:25,556 INFO EhCacheManagerFactoryBean  - Shutting down EhCache CacheManager
2015-06-09 09:54:25,574 INFO SimpleHanlder  - Stop socket handler.
2015-06-09 09:54:25,576 INFO LocalContainerEntityManagerFactoryBean  - Closing JPA EntityManagerFactory for persistence unit 'Oracle'
2015-06-09 09:54:25,579 INFO ShutDownHook  - Socket server shutdown 

此方法可以实现在系统退出时对资源的关闭及缓存数据清理等功能,是一个非常使用的功能。

文中部分内容来自其他博文,代码是我项目中的代码。如有雷同,请勿见怪。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK