oddjob之smooth关闭程序
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关闭程序的更多相关文章
- android的原理,为什么不需要手动关闭程序
转自android的原理,为什么不需要手动关闭程序 不用在意剩余内存的大小,其实很多人都是把使用其他系统的习惯带过来来了. Andoird大多应用没有退出的设计其实是有道理的,这和系统对进程的调度机制 ...
- 批处理--批量打开程序&批量关闭程序
批量打开程序 start D:\work\RunSvr01\IceFire88.01.exe start D:\work\RunSvr02\IceFire88.02.exe start D:\work ...
- CMD命令利用tasklist与taskkill关闭程序
昨天远程服务器后,服务器无故卡住了,鼠标各种延迟与无反应,想在进程管理器里关闭程序也卡住,想点击重启系统也卡死无反应.纠结后win+R打开了cmd用shutdown重启才算搞定.重启期间思考了下,如何 ...
- 关于Cocos2d-x程序运行时候提示关闭程序的框框的解决方法
1.这个情况是资源没有被加载的表现 如果AppDelegate.cpp里面没有文件索引的语句 FileUtils::getInstance()->addSearchPath("res& ...
- 使用VBS打开程序和关闭程序
下面这个是先执行程序后,然后再结束程序. Dim Wsh Set Wsh = WScript.CreateObject("WScript.Shell") '下行是设置延时启动时间 ...
- C# 设置程序最小化到任务栏右下角,鼠标左键单击还原,右键提示关闭程序
首先设置程序最小化到任务栏右下角 先给窗口添加一个notifyIcon控件 为notifyIcon控件设置ICO图标(不设置图标将无法在任务栏显示) 给notifyIcon控件添加点击事件 然后是最小 ...
- win7或win2008系统中,出现【已停止工作,联机检查解决方案并关闭该程序,关闭程序】解决方法!
win7或win2008系统中,出现[已停止工作,联机检查解决方案并关闭该程序,关闭程序]解决方法! 经过摸索,点击[控制面板]-[操作中心]-[更改操作中心设置]-[问题报告设置]-[从不检查解决方 ...
- 如果通过脚本来关闭程序-linux
正常情况下在linux关闭一个程序最好是走正常的关闭流程,不要直接杀死进程,这样程序的稳定性确实会收到影响,但是如果想通过脚本来关闭程序正常情况下比较困难的,我便采取了这种暴力的方法-直接杀死进程. ...
- WIn7系统下 打开.exe程序出现已停止工作关闭程序之解决办法
新装WIN7系统出现 .NET组建没有安装 可到官网下载安装 NETFx4.0 运行MVB 上位机SIM.EXE出现应用程序已停止工作问题 解决办法: 需关闭WIN7 DEP 如下 开始-运行( ...
随机推荐
- vs重复编译
VS用了这么久都没有这样的问题,昨天突然发现在自己电脑时间不对了,就调了下,以后这问题都来了.每次运行项目都要重新编译下,不管改不改底层代码.这让我很痛苦,浪费大量时间,找了好久才得到答案: .时间问 ...
- 【BZOJ4026】dC Loves Number Theory 分解质因数+主席树
[BZOJ4026]dC Loves Number Theory Description dC 在秒了BZOJ 上所有的数论题后,感觉萌萌哒,想出了这么一道水题,来拯救日益枯竭的水题资源. 给 ...
- 小程序发起post请求回调成功没有数据
get请求时为 header:{ "content-type":'application/json' },POST 请求会将data的值放在Request Payload里面,而不 ...
- 加密php源代码
<?php function RandAbc($length = "") { //返回随机字符串 $str = "ABCDEFGHIJKLMNOPQRSTUVWXY ...
- 【python】-- 文件操作
一.概述 我们工作中需要经常操作文件,下面就讲讲如何用Python操作文件 1.文件操作的流程: 打开文件,得到文件句柄赋值给一个变量 通过文件句柄,对文件进行操作 关闭文件 #获取文件句柄 f = ...
- 关于Android app的launcher图标更换后,仍然显示默认的ic_launcher图标的解决方法
<h1>概要</h1>在做手机适配的时候,遇到了一个很奇怪的问题,在1080x720的手机可以正常显示替换的ic_launcher.png图标,但是在1920x1080的手机上 ...
- PAT 1054. 求平均值 (20)
本题的基本要求非常简单:给定N个实数,计算它们的平均值.但复杂的是有些输入数据可能是非法的.一个“合法”的输入是[-1000,1000]区间内的实数,并且最多精确到小数点后2位.当你计算平均值的时候, ...
- oracle chain
[oracle@tyger dbs]$ sqlplus / as sysdba SQL*Plus: Release 10.2.0.1.0 - Production on Tue May 6 13:02 ...
- Codeforces Round #254 (Div. 2)B. DZY Loves Chemistry
B. DZY Loves Chemistry time limit per test 1 second memory limit per test 256 megabytes input standa ...
- Bootstrap学习1--响应式导航栏
备注:最新Bootstrap手册:http://www.jqhtml.com/bootstraps-syntaxhigh/index.html <nav class="navbar n ...