You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 15:00:09