【问题标题】:How to resume Java command line tool execution upon restart如何在重新启动时恢复 Java 命令行工具的执行
【发布时间】:2020-12-15 22:55:39
【问题描述】:

我正在开发一个 Java 命令行工具,其工作原理如下:

  1. 下载文件(其中包含一些键/值数据对)
  2. 处理整个文件并将键/值对存储在内存中的 TreeMap 中(按键排序)。
  3. 遍历 TreeMap 并将每个键/值映射条目传递给外部库。因此,基本上它的工作是按“键”对键/值条目进行排序,然后将它们传递给外部方法。
Sample file content (key-value pairs in JSON):
[{   
      "key" : 2
      "value" : "version2Content"
 },
 {   
      "key" : 1
      "value" : "version1Content"
 }, 
 {   
      "key" : 3
      "value" : "version3Content"
 }]

CLI 工具中的伪代码:

List<VersionPair> pairs = getVersionPairsFromJSON(input); 

TreeMap<Long, String> orderedEntries = new TreeMap<>();

for (VersionPair pair : pairs) {
    orderedEntries.put(pair.getKey(), pair.getVersionContent());
}

for (Map.Entry<Long, String> entry : orderedEntries) {
    externalMethod.sendVersion(entry.getKey(), entry.getValue())
        .whenComplete((metadata, error) -> {
            if (error != null) {
                System.err.println("Failed to send Version with key: " + entry.getKey() + ", with content: " + entry.getKey());
            }
        });
}

// POJO for VersionPair
public class VersionPair {
    Long key;
    String versionContent;
    ...
    // constructor, getters and setters
}
public CompletableFuture<Metadata> externalMethod(Long key, String versionContent);

在这里,对externalMethod 的调用顺序应严格基于JSON 文件中keys 的排序顺序(由于我的应用程序的性质)。例如:

externalMethod.sendVersion(1, "version1Content");
externalMethod.sendVersion(2, "version2Content");
externalMethod.sendVersion(3, "version3Content");

我想知道是否可以从停止的地方继续执行此工具,以防由于某种原因终止执行。 (例如,用户按 Ctrl+C)。假设文件内容保持不变。

我的用例还要求对于给定的键/值对,不能多次调用外部库方法。因此,如果在为某些键/值对调用外部库后程序停止了,我需要从程序停止的地方恢复,而不是重新开始。

是否可以使用 Java 命令行工具实现此行为?如果没有,我可以知道我们还有哪些其他选择可以实现这一目标?

提前致谢!

【问题讨论】:

  • 在没有看到代码的情况下提供指导有点困难,或者至少更详细地描述了您如何遍历树结构。如果您在一个集合上进行迭代,您将不得不就您想要的效率做出一些决定,因为您可能已经知道,TreeMap 没有索引。添加相关代码,您会得到更好的答案,因为现在,您要求人们猜测(不必要地)。
  • 只是另一个问题:您没有说明您的文件是否会随着时间的推移而发生变化(我怀疑确实如此)。如果是这样,就没有有意义的方法来恢复中断的操作。如果在多线程环境中更改此文件,那么最好丢弃不完整的运行并重新开始。知道运行是否不完整更容易实现,并保证您的结果有效(在您的工具进行完整运行时)。
  • 感谢您的回复!我在问题中添加了伪代码。假设文件内容保持不变。我已经使用 TreeMap 来排序键,但如果它们在这个特定用例中有任何优势,我愿意使用其他替代方法。
  • 为什么你甚至希望它从最后一点恢复?这似乎只会产生很多意想不到的结果。如果文件内容保持不变,为什么还要对其进行操作?只返回它之后会返回的东西

标签: java command-line-interface resume application-restart


【解决方案1】:

我猜你的用例是你想为最终用户构建一个命令行应用程序以将数据提交到外部系统。

为了实现“恢复”过程,这就需要“持久化”存储记住它“停止”的时间点。

因此,您可能需要包含“基于文件”的数据库,例如 H2、HSQL 等或使用简单的文本文件,以记住已处理的记录。

假设你的命令行是这样的:java -jar app.jar data1.json,那么在你的程序中可能会立即创建一个data1-inprogress.dat文件。然后写下您已成功处理 externalMethod 的每条记录。

因此,如果应用程序被中断,并且用户重新运行相同的命令,您的程序可以确定任何 data1.json 有 data1-inprogress.dat 表示未完成。然后你就可以开始编写 data1.json 和 dat1-inprogress.dat 之间的所有条件语句,以确保你的程序不会重新处理旧数据。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-02-24
    • 2013-02-04
    • 2021-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-26
    • 2018-10-03
    相关资源
    最近更新 更多