您当前的位置:首页 > 互联网教程

如何设计java应用程序的平滑停止

发布时间:2025-05-21 09:26:01    发布人:远客网络

如何设计java应用程序的平滑停止

一、如何设计java应用程序的平滑停止

程序的退出就像关机一样,我们希望关机时平滑关机,保证所有应用程序的数据都保存了。就像现在在写得blog,希望关机的时候能被保存好到草稿箱里。

我们的的java程序中经常有一种常驻的任务或服务,如消息消费端、服务提供者,我们期望停止也是平滑的不会出现事务执行到一半产生脏数据。

java对这块的支持是通过钩子线程实现。每个java进程都可以注册钩子线程,钩子线程程在程序退出的前被执行(kill-9强制退出除外)。注册钩子线程代码如下:

Runtime.getRuntime().addShutdownHook(t);

我们可以在钩子线程里做一些善后数据清理等事情,以保证程序是平滑退出的。

一般服务或框架运行都要考虑其生命周期:

如spring容器的context.stop()方法。

再如线程池ExecutorService的shutdown方法,它会保证不接受新任务,并把未执行完的任务做完。

我们再设计服务的时候也要考虑到停止时的stop方法,以便于退出时由钩子线程调用。

注册了钩子线程后,程序收到退出信号后,会保持程序运行,直到钩子线程执行完毕,才把程序的所有线程停止并退出,下面示例代码可以说明这一点:

public static void main(String[] args){

Runtime.getRuntime().addShutdownHook(new Thread(){

Thread.currentThread().sleep(5000);

} catch(InterruptedException e){

System.out.println("clean task1 completed.");

Runtime.getRuntime().addShutdownHook(new Thread(){

Thread.currentThread().sleep(10000);

} catch(InterruptedException e){

System.out.println("clean task2 completed");

Thread.currentThread().sleep(1000);

System.out.println("sub thread is running");

} catch(InterruptedException e){

===============================================================================

注意点:钩子线程里只处理善后,目标是尽可能快的退出且不保证有脏数据。如果钩子线程里做过多事情,或者发生阻塞,那么可能出现kill失效,程序不能退出的情况,这是需要强制退出。

如以下程序会导致kill失效,需要强制退出,因为钩子线程阻塞了:

public static void main(String[] args){

Runtime.getRuntime().addShutdownHook(new Thread(){

synchronized(ShutdownFileTest.class){

ShutdownFileTest.class.wait();

} catch(InterruptedException e){

Thread.currentThread().sleep(1000);

System.out.println("sub thread is running");

} catch(InterruptedException e){

触发程序退出的在前面已经提到过,但是为了停止方便、安全和优雅,一般我们推荐几种操控性更强的退出机制。常见的推荐机制有以下几种:

在linux里用的比较多,向进程发送退出信号,java进程收到后平滑退出。

系统创建一个shutdown file.并监听shutdown file是否存在。如果发现shutdown file不存在了,那么调用System.exit,将程序退出。

如果期望只有特定的人才能终止该程序,那么你可以给文件设定权限,这样就只有特定的人可以终止程序。

public class ShutdownFileTest{

public static void main(String[] args){

Thread.currentThread().sleep(1000);

System.out.println("sub thread is running");

} catch(InterruptedException e){

File shutDownFile= new File("a.shutdown");

shutDownFile.createNewFile();

// watch for file deleted then shutdown

Thread.currentThread().sleep(1000);

} catch(InterruptedException e){

3.打开一个端口,监听端口里的命令,收到命令后调用System.exit。

通过JMX的mbean远程控制来实现。

二、Java 6的核心特征和改进

1、Java功能的核心部分被描述为Java的一个专有组成部分(语言部分和它的核心工具),它对于Java的所有其它方面都起基础性的作用,从用户接口API到各种服务器端库等。下面我将分别谈谈Java SE 6在Java核心特征上的改进。新的Java编译器API允许从Java应用程序内部对Java源程序进行编译。在编译期间,应用程序可以访问库相关信息以及发出警告、错误和其它生成的信息。尽管这个特征似乎不是我常用的,但是我很快就发现了它的一些新用途。例如,我可以使用它来快速构建我所构建的程序的数据存取层。我可以编写代码来生成和编译用于存取应用程序的数据库表的类。最终结果是生成一个JAR文件,这个文件被进一步构建并作为系统的Ant脚本的一部分一同发布。能够从应用程序内部对类进行编译这一实现使得代码生成具有了交互性-我可以以交互方式来修改和构建类。

2、为了支持Java脚本编程,Java SE 6支持JSR 223,这是一种提供了到Java内部进行存取的脚本语言的框架标准。你可以定位脚本引擎并且在运行时调用它们以运行脚本。该脚本编程API允许你为选择的脚本语言提供Java支持。此外,该Web脚本框架允许脚本代码在任何Servlet容器内生成Web内容。

3、在调试方面,Java平台调试器(JPDA)也得到进一步增强,开发人员可以针对被锁定的监视对象检测死锁,并同时生成栈跟踪。通过在java.lang.OutOfMemory异常中包含一个完整的堆栈跟踪树并且在堆栈满时生成致命错误记录,Java SE 6进一步加强了内存漏洞分析和探测能力。另外,还增加了一个新的JVM选项以允许你在堆栈满时运行一个脚本。

4、注意当MBean属性值(包括在复杂类型内部的那些属性值)超过指定的门槛值时,对于JMX监视API的改进方面允许应用程序发送事件以传递指定的阀值。

5、对于Solaris 10用户来说,Hotspot JVM for Solaris针对Solaris DTrace系统调试工具提供了钩子机制以跟踪和显示内部JVM活动,例如垃圾收集、类加载、线程、锁机制等。我在JavaOne上面得到有关这方面特征的第一个演示程序,并因此为DTrace系统所提供的调试深度所深深吸引。当一个应用程序运行时,DTrace允许你在任何一处停止代码,观看所有已经加载的库(而不仅仅是Java库,也包括所有系统库),并且能够单步跟踪到Solaris内核中(直到硬件层)。Java对于这种高级调试工具的新的支持使该工具非常适合于系统级上的调试。我现在还记得以前在JVM中出现Solaris Signal-8错误时的情况,如果当时有这种支持,那将会节省我大量的分析时间。 Java SE 6中增加的安全方面的功能包括GSS/Kerberos集成,Java认证和针对LDAP认证的授权服务(JAAS),还有一个安全证书请求框架-它允许Java应用程序通过许多协议来请求安全证书。

三、编写java程序时如何强制结束程序

1、在编写Java程序时,有时需要强制程序提前结束运行。可以使用System.exit(1)语句来实现这一目标。这行代码会立即终止程序的执行,并返回一个退出码,通常用于指示程序的异常终止状态。

2、以下是一个示例代码,展示了如何在程序中使用System.exit(1)来强制终止程序执行:

3、public class Test{ public void doSomething(){ System.out.println("do something..."); System.exit(1); System.out.println("Cannot be done...");}}

4、在这个例子中,当执行到System.exit(1)时,程序会立即停止,并不会继续执行后续的println语句。因此,"Cannot be done..."这条输出信息永远不会被打印出来。

5、使用System.exit(1)时需要谨慎,因为它会立即终止整个虚拟机,包括所有线程的执行,这意味着任何未保存的状态都会丢失。在实际开发中,应尽量避免使用System.exit(1),除非程序遇到了无法继续运行的严重错误。

6、如果希望优雅地终止程序,可以考虑使用异常处理机制,通过抛出异常并捕获异常来实现程序的正常退出。这不仅能够保留部分程序状态,还能提供更友好的错误报告和处理机制。

7、此外,还可以利用JVM的其他特性,如设置终止钩子(Termination Hooks),来在程序退出时执行一些清理操作。这可以通过设置System.addShutdownHook方法来实现,这样可以在程序退出前执行自定义的清理代码,确保程序资源得到妥善释放。

8、总之,在编写Java程序时,合理使用System.exit(1)可以有效地解决某些特定场景下的程序终止问题,但在大多数情况下,推荐使用更灵活和安全的程序退出策略。