- 浏览: 378136 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
真的全站唯一:
描述的能不能准确一点,我也以为bigDecimal性能比dou ...
【性能】Java BigDecimal和double性能比较 -
zhanggang807:
学习到了。。以后会考虑往这方面设计
【java规范】Java spi机制浅谈 -
Xiong506:
<div class="quote_title ...
[监控]Btrace监控简单笔记 -
Xiong506:
<div class="quote_title ...
[监控]Btrace监控简单笔记 -
Bll:
找不到实现类
【java规范】Java spi机制浅谈
java应用程序退出的触发机制有:
1.自动结束:应用没有存活线程或只有后台线程时;
2.System.exit(0);
3.kill 或 ctrl+C;
4.kill -9 强制退出;
如何做到应用程序平滑停止
程序的退出就像关机一样,我们希望关机时平滑关机,保证所有应用程序的数据都保存了。就像现在在写得blog,希望关机的时候能被保存好到草稿箱里。
我们的的java程序中经常有一种常驻的任务或服务,如消息消费端、服务提供者,我们期望停止也是平滑的不会出现事务执行到一半产生脏数据。
java对这块的支持是通过钩子线程实现。每个java进程都可以注册钩子线程,钩子线程程在程序退出的前被执行(kill -9强制退出除外)。注册钩子线程代码如下:
Runtime.getRuntime().addShutdownHook(t);
我们可以在钩子线程里做一些善后数据清理等事情,以保证程序是平滑退出的。
一般服务或框架运行都要考虑其生命周期:
如spring容器的context.stop()方法。
再如线程池ExecutorService的shutdown方法,它会保证不接受新任务,并把未执行完的任务做完。
我们再设计服务的时候也要考虑到停止时的stop方法,以便于退出时由钩子线程调用。
注册了钩子线程后,程序收到退出信号后,会保持程序运行,直到钩子线程执行完毕,才把程序的所有线程停止并退出,下面示例代码可以说明这一点:
public class ShutDownTest { public static void main(String[] args) { //注册第一个钩子 Runtime.getRuntime().addShutdownHook(new Thread() { public void run() { try { Thread.currentThread().sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("clean task1 completed."); } }); //注册第二个钩子 Runtime.getRuntime().addShutdownHook(new Thread() { public void run() { try { Thread.currentThread().sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("clean task2 completed"); } }); //启动子线程 new Thread() { public void run() { while (true) { try { Thread.currentThread().sleep(1000); System.out.println("sub thread is running"); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); //程序退出 System.exit(0); } }
程序输出:
sub thread is running sub thread is running sub thread is running sub thread is running clean task1 completed. sub thread is running sub thread is running sub thread is running sub thread is running sub thread is running clean task2 completed
===============================================================================
注意点 :钩子线程里只处理善后,目标是尽可能快的退出且不保证有脏数据。如果钩子线程里做过多事情,或者发生阻塞,那么可能出现kill失效,程序不能退出的情况,这是需要强制退出。
如以下程序会导致kill失效,需要强制退出,因为钩子线程阻塞了:
public class ShutDownTest { public static void main(String[] args) { //注册钩子 Runtime.getRuntime().addShutdownHook(new Thread() { public void run() { synchronized (ShutdownFileTest.class) { try { ShutdownFileTest.class.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } }); //启动子线程 new Thread() { public void run() { while (true) { try { Thread.currentThread().sleep(1000); System.out.println("sub thread is running"); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); System.exit(0); } }
程序退出机制选择
触发程序退出的在前面已经提到过,但是为了停止方便、安全和优雅,一般我们推荐几种操控性更强的退出机制。常见的推荐机制有以下几种:
1.kill
在linux里用的比较多,向进程发送退出信号,java进程收到后平滑退出。
2.shutdownfile
系统创建一个shutdown file.并监听shutdown file是否存在。如果发现shutdown file不存在了,那么调用System.exit,将程序退出。
如果期望只有特定的人才能终止该程序,那么你可以给文件设定权限,这样就只有特定的人可以终止程序。
以下代码是个简单的例子:
import java.io.File; import java.io.IOException; public class ShutdownFileTest { public static void main(String[] args) { // 启动子线程 new Thread() { public void run() { while (true) { try { Thread.currentThread().sleep(1000); System.out.println("sub thread is running"); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); //启动shutdownfile监听线程 new Thread() { public void run() { File shutDownFile = new File("a.shutdown"); // create shut down file if (!shutDownFile.exists()) { try { shutDownFile.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } // watch for file deleted then shutdown while (true) { try { if (shutDownFile.exists()) { Thread.currentThread().sleep(1000); } else { System.exit(0); } } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); } }
3.打开一个端口,监听端口里的命令,收到命令后调用System.exit。
这个似乎不常见,也比较麻烦。
4.JMX
通过JMX的mbean远程控制来实现。
在这个链接里有看到例子:how-to-stop-java-process-gracefully
评论
1. kill pid
2.触发jvm的addShutdownHook。
3.如果在spring容器中,触发springbean的destroy-method回调方法。
但不同的应用场景要做到平滑停止面临不一样的问题,比如一台服务Server,不断有请求过来,如果要停止,已经执行一半的事务应该如何处理,如何平滑停止保证不会产生脏数据?期待博主能有更深入的分析。
发表评论
-
【java规范】Java spi机制浅谈
2012-04-24 23:04 45838最近看到公司的一些框架和之前看到的开源的一些框架的一些服务发现 ... -
Xml ResourceBundle简单实现
2012-04-17 21:45 4452ResourceBundle主要是用于和本地语言环境相关的一些 ... -
【maven】多子模块maven模板工程archetype创建过程
2012-04-02 20:55 17654最近项目里需要创建一 ... -
【java并发】juc Executor框架详解
2012-02-26 13:55 12494Executor 框架是 juc 里提供的线程池的实现。 ... -
【java并发】juc高级锁机制探讨
2012-02-23 00:52 8694最近在看一些j ... -
【java并发】基于JUC CAS原理,自己实现简单独占锁
2012-02-14 13:47 7848synchronized的基本原理回 ... -
[NoSQL]MongoDB初体验
2012-01-05 16:06 3964因为未来业务发展的一 ... -
【JDBC,数据库】Oracle date和timestamp类型混用时需要注意的索引失效问题
2011-12-14 15:27 89531.关于 Oracle date和timestamp类型 D ... -
【JVM】HotSpot JVM内存管理和GC策略总结
2011-12-13 22:05 15952JVM的相关知识是学习java ... -
【性能】JDBC PreparedStatement和连接池PreparedStatement Cache学习记录
2011-12-08 17:20 16871之前看JDBC规范的时候对PreparedStatement只 ... -
32位机器下的一个java.lang.OutOfMemoryError错误分析
2011-10-17 11:19 2595昨天在本人windows机器( ... -
【Spring】IOC核心源码学习(三):bean标签和自定义标签实现原理
2011-09-25 11:13 9684接上文: 【Spring】IOC核心源码学习(二):容器初始 ... -
【Spring】IOC核心源码学习(二):容器初始化过程
2011-09-21 21:03 23645接上文 啃啃老菜: Spring IOC核心源码学习(一 ... -
[监控]Btrace监控简单笔记
2011-09-09 10:57 5037前阵子看了公司网站的一个cache 命中率统计的btrace监 ... -
DBCP数据源配置项记录
2011-09-01 20:22 2994网站最近发生了数据库连接爆掉的问题。排查了下各个应用存在 ... -
【性能】Java BigDecimal和double性能比较
2011-08-28 20:06 14247我们知道 java 里面有个 BigDecimal ... -
【Spring】IOC容器并发条件下,可能发生死锁
2011-08-28 17:07 69211.背景 上周在生产环境应用启 ... -
JDK7 AIO 初体验
2011-08-17 19:20 2578JDK7 AIO初体验 JDK7已经releas ... -
啃啃老菜:Spring IOC核心源码学习(一)
2011-08-14 13:57 7521啃啃老菜: Spring IOC核心源码 ... -
如果要用java实现算法,一定慎用递归
2011-04-06 20:41 12947现象 : 递归是我们很经典的一种算法实现,可以很好的 ...
相关推荐
Java Service Wrapper是一个强大的工具,它允许开发者将Java应用程序轻松地包装为Windows系统服务,以便在操作系统启动时自动启动Java程序,并能实现与系统服务相同的管理功能,如自动重启、日志记录等。这个工具...
- 使用Java语言作为后台处理的主要编程语言,因为Java是Android应用程序开发的基础。 - 结合Android Studio开发环境,利用其提供的工具和库来构建用户界面和管理应用程序逻辑。 - 资料来源包括教师讲解的Java和...
此外,为了使风扇转动看起来更加自然,可能还应用了一些平滑动画技术,如缓动函数(easing function),使得速度变化更加平滑。 在实际编程中,为了使代码结构清晰、易于维护,可能采用了面向对象的设计原则,将...
Java是一种广泛使用的编程语言,尤其在开发Web应用程序和桌面应用程序方面具有强大能力。"JAVA小动画"这个压缩包文件很可能包含了一些使用Java Applet技术编写的简单动画程序,非常适合Java初学者用来学习和理解基本...
Java Tomcat监控程序是用于确保Web应用程序持续稳定运行的重要工具。在Java开发环境中,Tomcat是一个广泛使用的开源应用服务器,特别适用于运行Java Servlets和JavaServer Pages(JSP)。为了提高系统的可靠性和稳定...
在Java编程语言中,创建一个滚动字幕程序是一项常见的任务,尤其在开发用户界面或多媒体应用时。这个程序的核心目标是让文字在指定区域里连续滚动显示,类似于电视新闻底部的跑马灯效果。下面我们将深入探讨如何实现...
在Java编程中实现贪吃蛇游戏时,多线程技术的应用可以使游戏更加流畅且具有实时性。以下是对这个多线程Java程序的一些详细解释。 1. **线程基础** - 在Java中,线程是程序执行的最小单位,可以同时执行多个任务。...
项目执行有两种方式:作为应用程序和Applet。在MyEclipse中,可以直接运行项目,观察程序的运行效果。如果打算长期在MyEclipse中工作,可以考虑为Application和Applet声明包,如com.px1987.animation。这样做的好处...
理解并掌握这些工具和概念对于开发动态、交互性强的Java应用程序至关重要。通过实践和研究如"java animation on the procedures for hand"这样的示例,开发者可以进一步提升他们的Java动画技能。
Java GUI(图形用户界面)是Java编程语言中用于创建用户交互界面的一部分,它允许开发者构建桌面应用程序,提供视觉反馈和用户交互。在这个“java GUI做的抽奖转盘”项目中,我们很可能看到一个利用Java Swing或...
Java提供了Java Sound API来处理音频播放,包括加载、播放、暂停和停止音效。 七、游戏对象和状态管理 游戏中的对象,如角色、敌人、道具等,都有各自的状态和行为。通过设计良好的类结构和状态机,可以有效地管理...
在心率测量领域,开发一款基于Java的应用程序可以为用户提供便捷的健康监测方式。通过指尖检测脉搏,软件能够分析并计算出用户的心率。在这个项目中,我们看到的是一系列反编译后的Java源代码文件,包括c.java、d....
Java3D是一个强大的Java库,专门用于在Java应用程序中创建和展示三维图形。它由Sun Microsystems开发,并在Java Community Process (JCP) 的JSR 23D规范下定义。这个"java3D的jar包"是Java3D库的核心组成部分,提供...
理解如何正确管理和加载外部资源是Java应用程序开发的重要部分。 8. **设计模式**: 良好的代码结构可能采用了设计模式,如单例模式用于管理图片加载服务,工厂模式用于创建不同类型的特效,策略模式用于动态切换...
2. **Swing库**:Java的Swing库用于构建GUI应用程序。在这个项目中,我们需要使用`JFrame`来创建主窗口,`JPanel`作为小球移动的画布,以及`Graphics`类进行绘图操作。 3. **图形绘制**:利用`Graphics`类的`...
Java动画编程是计算机图形学与Java技术结合的产物,它允许开发者在Java平台上创造...总结来说,本文档对于Java动画编程技术的优化提供了宝贵的理论指导和实践建议,对开发高质量的Java动画应用程序具有重要的参考价值。
- `Applet`类是Java中用于创建可以嵌入到网页中的小型应用程序的基本类。 - 我们将继承`Applet`类,并重写其`paint`方法来绘制我们的滚动文本。 2. **字体设置**: - 通过`GraphicsEnvironment`类获取系统可用的...
1. **生成应用程序框架**:使用AppWizard生成基础的应用程序框架。 2. **编辑菜单资源**:在主菜单中添加“时钟控制”菜单项,包含启动时钟、停止时钟和时间设置等子菜单项。 3. **添加消息处理函数**:利用...
7. **动画效果**:为了增加游戏的视觉吸引力,开发者可能会使用延时或帧率控制(例如使用`java.util.Timer`类)来平滑地显示方块的下落和旋转,使游戏看起来更流畅。 8. **得分系统**:每当消除一行或多行,游戏...
Java Applet是Java平台的一部分,允许开发者创建可以在Web浏览器中运行的小型应用程序。要创建一个Applet,你需要继承`java.applet.Applet`类或者使用JApplet(自Java 1.2版本起推荐使用),并覆盖必要的方法,如`...