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. Nginx教程

    Nginx教程 1.背景 介绍 Nginx是一个高性能的HTTP服务器,以及反向代理服务器 组成 Ngnix有内核和模块组成.微结构的内核根据配置文件将一个请求映射到一个location块中,该loc ...

  2. 【基于rssi室内定位报告】rssi分布情况标识位置

    import matplotlib matplotlib.use('Agg') import numpy as np from numpy import array from matplotlib i ...

  3. thinkphp5, 模板继承、模板布局

    ---------------------------------------------------------------------------------------------------- ...

  4. RZ11 系统配置参数

    SAP系统配置参数详解[转] SAP 系统参数设置 path: /usr/sap/PRD/SYS/profile profile: PRD_DVEBMGS00_sapapp 如果您想查看所有的参数及当 ...

  5. matlab + c/c++ opencv 混合编程

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 辛苦原创所得,转载请注明出处 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ...

  6. 提供的STC89C52RC单片机GPS在LCD1602液晶只显示welcome to use问题?

    1.使用USB-TTL接GPS单独测试GPS定位在所处环境看是否能定位到. 2.检查自己使用的单片机是不是STC89C52RC型号,提供例程使用的这个型号单片机.如果使用其他51单片机,请先使用STC ...

  7. sonarQube使用maven进行检查

    1.在maven的中找到setting配置文件.在setting.xml中增加sonarqube配置.如下: <profiles> <profile> <id>so ...

  8. 3.09课·········for穷举和迭代

    for循环拥有两类:穷举和迭代穷举:把所有可能的情况都走一遍,使用if条件筛选出来满足条件的情况. 1.单位给发了一张150元购物卡,拿着到超市买三类洗化用品.洗发水15元,香皂2元,牙刷5元.求刚好 ...

  9. 回忆基础:制作plist文件

    -(void)creatPlistFileWithArr:(NSArray *)array{ //将字典保存到document文件->获取appdocument路径 NSString *docP ...

  10. java面试_数据库

    1.group by 根据表里的字段名分类,相同字段名只显示一行记录,通常与聚集函数max.min合用选择最大值最小值,或者与having合用筛选,结果按照group by的字段排序 例:select ...