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. Linux下,部署多个Tomcat

    1.复制一个已有的tomcat,并重命名: 2.打开tomcat--conf--server.xml:[共修改3处配置] <Server port="8005" shutdo ...

  2. (转)Java并发编程:阻塞队列

    原文地址: http://www.cnblogs.com/dolphin0520/p/3932906.html 一.几种主要的阻塞队列 自从Java 1.5之后,在java.util.concurre ...

  3. POJ 1584 A Round Peg in a Ground Hole【计算几何=_=你值得一虐】

    链接: http://poj.org/problem?id=1584 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=22013#probl ...

  4. Pipeline模式(netty源码死磕6)

    精进篇:netty源码死磕6  巧夺天工--Pipeline模式揭秘 1. 巧夺天工--Pipeline模式揭秘 1.1. Pipeline模式简介 管道的发名者叫,Malcolm Douglas M ...

  5. 【python】-- 类的继承(新式类/经典类)、多态

    继承 之前我们说到了类的公有属性和类的私有属性,其实就是类的封装,现在准备随笔的 是继承,是面向对象的第二大特性. 面向对象编程 (OOP) 语言的一个主要功能就是“继承”.继承是指这样一种能力:它可 ...

  6. Qt插件开发入门(两种方法:High-Level API接口,Low-Level API接口)

    Qt中为我们提供了两种开发插件的方式.一种是使用High-Level API接口,一种是使用Low-Level API接口.所谓High-Level API 是指通过继承Qt为我们提供的特定的插件基类 ...

  7. opengl绘制图片

    #include <GL/glew.h>#include <glut.h>#include "FreeImage.h"#include <stdio. ...

  8. python cookbook第三版学习笔记十八:可由用户修改的装饰器

    定义一个属性可由用户修改的装饰器: 在前面的介绍中使用装饰器来包装函数,这一章来介绍下如何让用户调整装饰器的属性. 首先来看下代码: from functools import wraps,parti ...

  9. C#调用大漠插件

    大漠插件是一个很不错的东西,在按键精灵和易语言里面用得很多,可以后台找图找字,写游戏自动脚本用得特别多.前面写一个微信的自动脚本,查了一些资料,易语言不太熟悉,按键精灵功能上可能不好实现,就找了些资料 ...

  10. 转的es6 =>函数

    原文地址 箭头函数=>无疑是ES6中最受关注的一个新特性了,通过它可以简写 function 函数表达式,你也可以在各种提及箭头函数的地方看到这样的观点--"=> 就是一个新的 ...