java程序的smooth关闭策略可以采用hook跟观察者的模式实现

无限等状态,如果状态出现可以关闭的事件则进行关闭

虚拟机的关闭通过钩子调用关闭,如果关闭失败,在超时时间内强制杀掉jvm

状态类

public interface State {

    public boolean isStoppable();

}
package com.s.stat;

/**
* A Stateful job implements this interface so that
* it's state can be discovered. State is used to
* control the flow of execution within Oddjob, as
* well as being a way of informing client applications
* of progress.
*
* @author Rob Gordon
*/
public interface Stateful { /**
* Add a job state listener.
*
* @param listener The listener.
*
*/
public void addStateListener(StateListener listener) ; /**
* Remove a job state listener.
*
* @param listener The listener.
*/
public void removeStateListener(StateListener listener); /**
* Get the last state event.
*
* @return The last State Event
*/
public StateEvent lastStateEvent(); }
package com.s.stat;

import java.io.Serializable;
import java.util.Date;
import java.util.EventObject; /**
* An instance of this class is produced when a job state changes. It is
* passed to all JobStateListeners.
*
* @author Rob Gordon
*/ public class StateEvent extends EventObject
implements Serializable { private static final long serialVersionUID = 20051026; static final String REPLACEMENT_EXCEPTION_TEXT = "Exception is not serializable, message is: "; private State state;
private Date time;
private Throwable exception; /**
* Used to replace a non serializable exception.
*
*/
class ExceptionReplacement extends Exception {
private static final long serialVersionUID = 20051217;
public ExceptionReplacement(Throwable replacing) {
super(REPLACEMENT_EXCEPTION_TEXT + replacing.getMessage());
super.setStackTrace(exception.getStackTrace());
}
} /**
* Constructor.
*
* @param job The source of the event.
* @param jobState The state.
* @param time the Time of the event.
* @param exception The exception if applicable, or null otherwise.
*/
public StateEvent(Stateful job, State jobState, Date time, Throwable exception) {
super(job);
if (jobState == null) {
throw new NullPointerException("JobState can not be null!");
}
this.state = jobState;
this.time = time;
this.exception = exception;
} /**
* Constructor.
*
* @param job The source of the event.
* @param jobState The state.
* @param exception The exception if applicable, or null otherwise.
*/
public StateEvent(Stateful job, State jobState, Throwable exception) {
this(job, jobState, new Date(), exception);
} /**
* Constructor.
*
* @param job The source of the event.
* @param jobState The state.
*/
public StateEvent(Stateful job, State jobState) {
this(job, jobState, null);
} @Override
public Stateful getSource() {
return (Stateful) super.getSource();
} /**
* Get the job state.
*
* @return The job state.
*/
public State getState() {
return state;
} /**
* Get the exception if applicable, null otherwise.
*
* @return The exception of null.
*/
public Throwable getException() {
return exception;
} /**
* Get the time of the event..
*
* @return The time.
*/
public Date getTime() {
return time;
} /**
* Override toString.
*/
public String toString() {
return "JobStateEvent, source=" + getSource() + ", " + state;
} }
package com.s.stat;

/**
* Implementors of this interface are able to listen to state events.
*
* @author Rob Gordon
*/ public interface StateListener { /**
* Triggered when the job state changes.
*
* @param event The job state event.
*/
public void jobStateChange(StateEvent event); }
package com.s;

import com.s.stat.StateEvent;
import com.s.stat.StateListener;
import com.s.stat.Stateful; public class Runner implements Runnable{
public static final String KILLER_TIMEOUT_PROPERTY = "shutdown.killer.timeout"; public static final long DEFAULT_KILLER_TIMEOUT = 15000L; /** Flag if program is being destroyed from the Shutdown Hook. */
private volatile boolean destroying = false; /** The killer thread time out. */
private final long killerTimeout; public Runner() {
String timeoutProperty = System.getProperty(KILLER_TIMEOUT_PROPERTY);
if (timeoutProperty == null) {
killerTimeout = DEFAULT_KILLER_TIMEOUT;
} else {
killerTimeout = Long.parseLong(timeoutProperty);
}
} @Override
public void run() {
// TODO Auto-generated method stub
Runtime.getRuntime().addShutdownHook(new ShutdownHook());
// Possibly wait for Oddjob to be in a stopped state.
new StopWait(new Stateful() { @Override
public void removeStateListener(StateListener listener) {
// TODO Auto-generated method stub } @Override
public StateEvent lastStateEvent() {
// TODO Auto-generated method stub
return null;
} @Override
public void addStateListener(StateListener listener) {
// TODO Auto-generated method stub }
}, Long.MAX_VALUE).run(); // 调用程序的stop } /**
* shutdown hook.
* <p>
* This Class has evolved quite a lot though trial and error due to
* a lack of understanding of JVM shutdown. Should this thread be a
* daemon? Current thinking is no because you don't want other daemon
* threads to terminate until has been shutdown properly.
*
*/
class ShutdownHook extends Thread { /** Killer thread will forcibly halt if it hasn't terminated
* cleanly. */
private Thread killer; /*
* (non-Javadoc)
* @see java.lang.Thread#run()
*/
public void run() { // logger.info("Shutdown Hook Executing."); // killer will just kill process if we can't stop in 15 sec
killer = new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(killerTimeout);
}
catch (InterruptedException e) {
// logger.debug("Killer thread interrupted and terminating.");
return;
}
// logger.error("Failed to stop Oddjob nicely, using halt(-1)");
Runtime.getRuntime().halt(-1);
}
}); // start the killer. Not sure it really need to be daemon but
// it does no harm.
// logger.debug("Starting killer thread.");
killer.setDaemon(true);
killer.start(); // 调用程序的关闭 // Nothing's hanging so we don't need our killer.
//TODO 判断程序是否调用自身的关闭程序,如果成功则单端killer
// killer.interrupt(); }
}
}
package com.s;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit; import com.s.stat.IsStoppable;
import com.s.stat.State;
import com.s.stat.StateEvent;
import com.s.stat.StateListener;
import com.s.stat.Stateful; /**
* A utility class to provide wait until stopped functionality.
* <p>
* The default timeout is 5 seconds before a {@link FailedToStopException}
* is thrown.
*
* @author rob
*
*/
public class StopWait { private final Stateful stateful; private final long timeout; /**
* Constructor with default timeout.
*
* @param stateful The thing to wait until stopped.
*/
public StopWait(Stateful stateful) {
this(stateful, 5000);
} /**
* Constructor where timeout can be specified.
*
* @param stateful The thing to wait until stopped.
* @param timeout The timeout. Note that a timeout of 0 or less is
* no timeout.
*/
public StopWait(Stateful stateful, long timeout) {
this.stateful = stateful;
this.timeout = timeout;
} /**
* Run the stop wait. This will block until the job stops or the
* timeout occurs.
*
* @throws FailedToStopException If timeout occurs.
*/
public void run() { if (new IsStoppable().test(
stateful.lastStateEvent().getState())) {
doWait();
}
} private void doWait() { final BlockingQueue<State> handoff = new LinkedBlockingQueue<State>(); class StopListener implements StateListener { @Override
public void jobStateChange(StateEvent event) {
handoff.add(event.getState());
}
}; StopListener listener = new StopListener(); stateful.addStateListener(listener); try {
while (true) { State state = handoff.poll(timeout, TimeUnit.MILLISECONDS);
if (state == null) {
}
if (!state.isStoppable()) {
return;
}
}
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
finally {
stateful.removeStateListener(listener);
}
}
}

oddjob之smooth关闭程序的更多相关文章

  1. android的原理,为什么不需要手动关闭程序

    转自android的原理,为什么不需要手动关闭程序 不用在意剩余内存的大小,其实很多人都是把使用其他系统的习惯带过来来了. Andoird大多应用没有退出的设计其实是有道理的,这和系统对进程的调度机制 ...

  2. 批处理--批量打开程序&批量关闭程序

    批量打开程序 start D:\work\RunSvr01\IceFire88.01.exe start D:\work\RunSvr02\IceFire88.02.exe start D:\work ...

  3. CMD命令利用tasklist与taskkill关闭程序

    昨天远程服务器后,服务器无故卡住了,鼠标各种延迟与无反应,想在进程管理器里关闭程序也卡住,想点击重启系统也卡死无反应.纠结后win+R打开了cmd用shutdown重启才算搞定.重启期间思考了下,如何 ...

  4. 关于Cocos2d-x程序运行时候提示关闭程序的框框的解决方法

    1.这个情况是资源没有被加载的表现 如果AppDelegate.cpp里面没有文件索引的语句 FileUtils::getInstance()->addSearchPath("res& ...

  5. 使用VBS打开程序和关闭程序

    下面这个是先执行程序后,然后再结束程序. Dim Wsh Set Wsh = WScript.CreateObject("WScript.Shell") '下行是设置延时启动时间 ...

  6. C# 设置程序最小化到任务栏右下角,鼠标左键单击还原,右键提示关闭程序

    首先设置程序最小化到任务栏右下角 先给窗口添加一个notifyIcon控件 为notifyIcon控件设置ICO图标(不设置图标将无法在任务栏显示) 给notifyIcon控件添加点击事件 然后是最小 ...

  7. win7或win2008系统中,出现【已停止工作,联机检查解决方案并关闭该程序,关闭程序】解决方法!

    win7或win2008系统中,出现[已停止工作,联机检查解决方案并关闭该程序,关闭程序]解决方法! 经过摸索,点击[控制面板]-[操作中心]-[更改操作中心设置]-[问题报告设置]-[从不检查解决方 ...

  8. 如果通过脚本来关闭程序-linux

    正常情况下在linux关闭一个程序最好是走正常的关闭流程,不要直接杀死进程,这样程序的稳定性确实会收到影响,但是如果想通过脚本来关闭程序正常情况下比较困难的,我便采取了这种暴力的方法-直接杀死进程. ...

  9. WIn7系统下 打开.exe程序出现已停止工作关闭程序之解决办法

    新装WIN7系统出现  .NET组建没有安装  可到官网下载安装 NETFx4.0 运行MVB 上位机SIM.EXE出现应用程序已停止工作问题 解决办法: 需关闭WIN7 DEP  如下 开始-运行( ...

随机推荐

  1. lua例子getglobal()

    #include <stdio.h> #define MAX_COLOR 255 extern "C" { #include "lua-5.2.2/src/l ...

  2. maven;spring;pom

    [说明]因为对环境配置文件理解的不充分,遇到问题经常是无法独自解决,特别是maven和javaweb的转换,也是糊里糊涂的,今天就又出问题了. [说明] 一:今日完成 1)任务二的效果展示看的我一脸懵 ...

  3. RedisTemplate访问Redis数据结构(介绍和常用命令)

    Redis 数据结构简介 Redis 可以存储键与5种不同数据结构类型之间的映射,这5种数据结构类型分别为String(字符串).List(列表).Set(集合).Hash(散列)和 Zset(有序集 ...

  4. apache虚拟主机配置: 设置二级目录访问跳转

    <VirtualHost *:> DocumentRoot "d:/www/abc" ServerName www.abc.com Alias /course &quo ...

  5. JavaScript-Confirm用法

    function checkMobileBind() {    if(confirm('您尚未绑定手机,是否前往绑定?'))    {        window.location='http://m ...

  6. Mybatis sql注入问题

    预编译方式,即PreparedStatement,可以防注入:#{id} <select id="getBlogById" resultType="Blog&quo ...

  7. spring AOP理解和相关术语

    一.AOP理解 AOP:横向抽取机制,底层使用代理方式实现. 示例: 现有LogDAO接口以及实现Log接口的Log类.类有add的方法,现在要打印add方法的开始时间和结束时间.(即增强Log的ad ...

  8. js:深入函数的定义

    函数定义方式: 1.function fun1(){alert("fun1");}  //函数就是一个很特殊的对象.是一个Function的实例.事实上在内存中存储的操作是通过一个 ...

  9. redis学习笔记 - Pipeline与事务

    原文 Redis提供了5种数据结构,但除此之外,Redis还提供了注入慢查询分析,Redis Shell.Pipeline.事务.与Lua脚本.Bitmaps.HyperLogLog.PubSub.G ...

  10. swap 内存不足

    参考:https://stackoverflow.com/questions/5682854/why-is-the-linker-terminating-on-me-when-i-build-clan ...