Java中如何修改Restore类实现系统恢复后仅执行关机后事件?
解决Java温室控制系统恢复后仅执行关机后事件的问题
我正在开发一个Java温室控制系统,需要在PowerOut、WindowMalfunction等事件触发关机后恢复系统状态,要求恢复后只执行关机之后的事件,而非重播所有起始事件。当前实现恢复后会输出关机前的所有历史事件,不符合预期。我采用序列化保存系统状态,且通过Fixable接口处理恢复时的修复逻辑。
预期行为
执行java GreenhouseControls -d dump.out时,恢复系统并仅输出关机后的事件:
System restored from dump.out Restored system state: Power On: false Resuming system... Bing! Terminate
实际行为
恢复后重播所有起始事件:
Restored system state: Power On: false Resuming system... Restarting system Thermostat on night setting Light is on Light is off ... (输出所有初始事件)
解决方案
核心问题是当前系统没有记录关机时的事件执行进度,导致恢复时从头开始执行所有事件。通过以下步骤修改即可解决:
1. 在GreenhouseControls中添加事件进度跟踪字段
新增可序列化的字段记录下一个待执行的事件索引,关机时将该状态与系统状态一起保存:
import java.io.*; import java.util.ArrayList; import java.util.List; public class GreenhouseControls implements Serializable { // 原有字段保持不变 protected boolean light = false; protected boolean water = false; protected String thermostat = "Day"; protected boolean fans = false; protected boolean windowok = true; protected boolean poweron = true; private int errorcode; // 新增:跟踪下一个要执行的事件索引 private int nextEventIndex = 0; // 存储所有待执行事件的队列(需为可序列化类型,比如ArrayList) private List<Runnable> eventQueue = new ArrayList<>(); // 原有Fixable接口和PowerOn类保持不变 public interface Fixable { void fix(); void log(); } public class PowerOn implements Fixable { @Override public void fix() { poweron = true; errorcode = 0; } @Override public void log() { System.out.println("Power restored"); } } // 新增:执行完事件后更新索引 public void incrementEventIndex() { nextEventIndex++; } // 新增:获取当前待执行事件的索引 public int getNextEventIndex() { return nextEventIndex; } // 新增:获取事件队列的方法 public List<Runnable> getEventQueue() { return eventQueue; } // 修改shutdown方法,确保事件索引和队列被序列化保存 public void shutdown(int errorcode, String errorMessage) { this.errorcode = errorcode; try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("dump.out"))) { out.writeObject(this); } catch (IOException e) { e.printStackTrace(); } System.exit(0); } // 原有方法保持不变 public int getError() { return errorcode; } public Fixable getFixable(int errorcode) { if (errorcode == 2) return new PowerOn(); return null; } }
2. 修改Restore类,从记录的索引处开始执行事件
恢复完成后,跳过已执行的事件,直接从保存的索引位置启动后续事件:
import java.io.*; import java.util.List; public class Restore { private GreenhouseControls gc; public Restore(String filename) { try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(filename))) { gc = (GreenhouseControls) in.readObject(); System.out.println("System restored from " + filename); } catch (IOException | ClassNotFoundException e) { System.out.println("Error during system restore: " + e.getMessage()); e.printStackTrace(); } } public void fixAndResume() { if (gc != null) { System.out.println("Restored system state:"); System.out.println("Power On: " + gc.poweron); // 执行故障修复逻辑 if (gc.getError() != 0) { GreenhouseControls.Fixable fixable = gc.getFixable(gc.getError()); fixable.fix(); fixable.log(); } System.out.println("Resuming system..."); // 从记录的索引开始执行后续事件 int startIndex = gc.getNextEventIndex(); List<Runnable> eventQueue = gc.getEventQueue(); for (int i = startIndex; i < eventQueue.size(); i++) { eventQueue.get(i).run(); gc.incrementEventIndex(); // 执行后更新索引,避免重复执行 } } } public static void main(String[] args) { // 处理命令行参数,匹配-d触发恢复逻辑 if (args.length >= 2 && args[0].equals("-d")) { Restore restore = new Restore(args[1]); restore.fixAndResume(); } } }
3. 调整系统启动逻辑
在GreenhouseControls的主方法中添加判断:如果命令行带有-d参数,则触发恢复流程;否则执行首次启动的事件初始化和执行逻辑,避免恢复时从头重播事件。
关键注意事项
- 事件队列必须使用可序列化集合(如
ArrayList),否则序列化时会丢失事件数据,恢复后无法获取后续事件。若事件本身不可序列化,可改为保存事件的唯一标识(如类型+参数),恢复时重新构建事件。 - 每次执行完一个事件后,必须调用
incrementEventIndex()更新索引,确保关机时保存的是正确的下一个事件位置。
内容的提问来源于stack exchange,提问作者Chris Furing
相关产品推荐
相关产品推荐

