Java利用ShutDownHook關閉系統資源

Java關閉鉤子

在Java程序中可以經過加入關閉鉤子,實現在程序退出時關閉資源的功能。
使用Runtime.addShutdownHook(Thread hook)向JVM加入關閉鉤子java

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命令幹掉進程spring

在Eclipse中使用關閉鉤子

在Eclipse中直接點擊Terminate關閉程序時不會觸發關閉鉤子的。緩存

在Linux下使用kill -9也是不會觸發鉤子的markdown

假設想在Eclipse中實現關閉鉤子的功能,需要另起一個線程監聽控制檯,在控制檯輸入Enter時關閉系統oracle

/** * <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的一些處理。app

<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方法。eclipse

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

        Runtime.getRuntime().addShutdownHook(new ShutDownHook(ct));

        //在正式部署時不需要如下的代碼,這段代碼僅供調試時使用
        Thread thread = new ExitThread();
        thread.start();
    }

終於效果例如如下socket

ide

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

此方法可以實現在系統退出時對資源的關閉及緩存數據清理等功能。是一個很使用的功能。post

文中部份內容來自其它博文,代碼是我項目中的代碼。

若有雷同。請勿見怪。 本文僅僅介紹怎樣使用。至於原理請問度娘和谷歌

相關文章
相關標籤/搜索