Java利用ShutDownHook关闭系统资源

作者: wencst 分类:JAVA,Uncategorized 发布时间: 2016-08-30 10:10 阅读: 1,854 次

Java关闭钩子

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

 public void addShutdownHook(Thread hook) {
        SecurityManagersm= 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 Loglogger= 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 Loglogger= LogFactory.getLog(getClass());
    private ConfigurableApplicationContext applicationContext;
    public ShutDownHook(ConfigurableApplicationContextapplicationContext){
        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) {
        ClassPathXmlApplicationContextct= new ClassPathXmlApplicationContext("applicationContext.xml");

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

最终效果如下

2015-06-09 09:43:51,233INFOClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@2e52cdcc:startupdate [Tue Jun 09 09:43:51CST2015];root of context hierarchy2015-06-09 09:43:52,263INFOXmlBeanDefinitionReader  - LoadingXML bean definitionsfrom classpath resource[applicationContext.xml]2015-06-09 09:43:55,559INFOXmlBeanDefinitionReader  - LoadingXML bean definitionsfrom classpath resource[applicationContext-service.xml]2015-06-09 09:43:55,724INFOXmlBeanDefinitionReader  - LoadingXML bean definitionsfrom classpath resource[applicationContext-db.xml]2015-06-09 09:44:01,358INFOPropertyPlaceholderConfigurer  - Loadingproperties filefrom classpath resource[jdbc.properties]2015-06-09 09:44:02,687INFOMLog  - MLogclientsusing slf4j logging.
2015-06-09 09:44:06,563INFO 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,930INFOLocalContainerEntityManagerFactoryBean  - BuildingJPA containerEntityManagerFactory forpersistence unit'Oracle'
2015-06-09 09:44:09,251INFOLogHelper  - HHH000204: Processing PersistenceUnitInfo[ name: Oracle ...]2015-06-09 09:44:13,400INFOVersion  - HHH000412: Hibernate Core {4.3.7.Final}
2015-06-09 09:44:13,404INFOEnvironment  - HHH000206: hibernate.properties notfound2015-06-09 09:44:13,439INFOEnvironment  - HHH000021: Bytecodeprovider name:javassist2015-06-09 09:44:15,016INFOVersion  - HCANN000001: Hibernate Commons Annotations {4.0.5.Final}
2015-06-09 09:44:15,660INFODialect  - HHH000400: Using dialect: org.hibernate.dialect.Oracle10gDialect
2015-06-09 09:44:15,739INFOLobCreatorBuilder  - HHH000422: Disablingcontextual LOB creationasconnection wasnull
2015-06-09 09:44:16,056INFOASTQueryTranslatorFactory  - HHH000397: Using ASTQueryTranslatorFactory
2015-06-09 09:44:21,032INFOEhCacheManagerFactoryBean  - Initializing EhCache CacheManager
2015-06-09 09:44:21,977INFOExitThread  -press ENTER to callSystem.exit(0)

2015-06-09 09:54:23,694INFOShutDownHook  - Start clean the login info.
2015-06-09 09:54:23,787INFOAbstractPoolBackedDataSource  - 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 asusername7_1_fromTB_DXP_USER_LOGIN_STATUS tbdxpuserl0_2015-06-09 09:54:25,555INFOClassPathXmlApplicationContext  - Closing org.springframework.context.support.ClassPathXmlApplicationContext@2e52cdcc:startup date[Tue Jun 09 09:43:51CST2015];root of context hierarchy2015-06-09 09:54:25,556INFOEhCacheManagerFactoryBean  - ShuttingdownEhCache CacheManager
2015-06-09 09:54:25,574INFOSimpleHanlder  - Stop socket handler.
2015-06-09 09:54:25,576INFOLocalContainerEntityManagerFactoryBean  - ClosingJPAEntityManagerFactory forpersistence unit'Oracle'
2015-06-09 09:54:25,579INFOShutDownHook  - Socketserver shutdown

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

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

如果文章对您有用,扫一下支付宝的红包,不胜感激!

欢迎加入QQ群进行技术交流:656897351(各种技术、招聘、兼职、培训欢迎加入)