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. hdu4063(圆与圆交+线段与圆交+最短路)

    写几何题总是提心吊胆.精度问题真心吓人. 其实思路挺简单的一道题,真是什么算法和几何double搞到一块,心里就虚虚的. 思路:求出所有圆之间的交点,然后用这些交点跑一遍最短路就可以了. Aircra ...

  2. C# RangeHelper

    /// <summary> /// Range Helper /// </summary> /// <typeparam name="T">&l ...

  3. jvm本身的多线程机制

    1 多线程环境下的构造函数调用 构造函数本身并没有隐式的同步,因为各个线程构建的是自己的对象,它们之间是不存在竞争关系的. 2 class loader在load class时被了sychronize ...

  4. hibernate Session的CRUD操作

    使用Session里面的方法进行CRUD操作 (1) 增加 save 方法 (2) 查找 get 方法(根据id查) (3) 修改 update 方法 (4) 删除 delete 方法 1.增加 /* ...

  5. 【学习】Spring 的 AOP :基于Annotation 的“零配置”方式

    转自:http://www.cnblogs.com/jbelial/archive/2012/07/20/2539123.html AOP(Aspect Orient Programming ) , ...

  6. linux shell 中数组使用方法介绍

    linux shell在编程方面比windows 批处理强大太多,不管是在循环.运算.已经数据类型方面都是不能比較的. 以下是个人在使用时候,对它在数组方面一些操作进行的总结. 1.数组定义 [che ...

  7. pinpoint-dubbo插件兼容泛化调用

    背景 dubbo插件中需要记录当前调用的接口和方法,但是在泛化调用的场景下,记录的接口和方法都变成了 com.alibaba.dubbo.rpc.service.GenericService:$inv ...

  8. LeetCode:移动零【283】

    LeetCode:移动零[283] 题目描述 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序. 示例: 输入: [0,1,0,3,12] 输出: [1,3 ...

  9. Linux中查找文件和文件内容的常用命令

    一.whereis <程序名称> 查找软件的安装路径-b 只查找二进制文件 -m 只查找帮助文件-s 只查找源代码-u 排除指定类型文件-f 只显示文件名-B <目录> 在指定 ...

  10. virtualbox 桥接 (转)

    virtualbox 自带的网络配置模式要么选择host-only,要么bridge,对于经常使用virtualbox的同学一定想要像vmware一样的nat配置,既可以让host访问guest,又可 ...