Java 命令行应用程序以某种方式保留状态

标签 java maven command-line

前言:如果这是一个非常愚蠢的错误或实际上有据可查的错误,我深表歉意。现在对我来说这似乎很奇怪而且完全没有意义。

应用

我有一个在 macOS 10.13.4 上的 IntelliJ IDEA Ultimate 中构建的 Java 命令行应用程序,它使用了下面列出的四个 Maven 库。其目的是从网站下载文件,并在此过程中浏览分页结果。

此应用程序的功能之一是能够保持循环运行,如果在完成当前扫描时经过了足够长的时间,则检查新结果。为此,它调用 Thread.sleep(remainingMillis) 作为 do-while block 中 while 条件的一部分。

问题

应用程序运行没有任何问题,但是在引入 Thread.sleep() 调用之后(我怀疑这是麻烦的行),出现了一些非常奇怪的行为:应用程序执行第一次运行没有问题,从配置的网站获取三个项目;然后将其配置为确保 60 秒后再次运行。然而,在随后的运行中,日志表明它开始查看第 31 页(作为示例),而不是扫描结果的第一页,在那里它没有找到任何结果。如果没有找到任何东西,尝试三遍中的两遍查看第 32 页,最后一次尝试查看第 33 页;然后它再次等待,直到扫描迭代开始后 60 秒过去。

我无法确认这一点,但它似乎在随后的扫描中继续计数:34、35,然后是 36,然后再次等待。但是,代码会建议,当 while 的另一次迭代开始时,这应该再次从 1 开始。

这可能是 IntelliJ 或 Java 的问题,它可能只需要清理 bin/obj 文件夹,但如果这是由于我的代码造成的,我宁愿知道它所以我不会遇到以后同样愚蠢的问题。

观察

几天后使用当前配置运行应用程序意味着它不会调用 Thread.sleep(),因为超过 60 秒后它会立即继续下一次迭代;发生这种情况时,奇怪的页面索引递增问题不会浮出水面 - 而是下一次迭代从第 1 页开始继续。

然后,在开始下一次迭代之前运行它,使其执行 Thread.sleep() 几秒钟,也没有导致问题……非常奇怪。这是梦吗?

代码

旁注:我添加了 Thread.currentThread().interrupt() 来尝试解决这个问题,但它似乎没有效果。

public static void main(String[] args) {
        do {
            startMillis = System.currentTimeMillis();
            int itemsFetched = startFetching(agent, config, record, 1, 0);
        } while (shouldRepeat(config.getRepeatSeconds(), startMillis));
    }

    private static boolean shouldRepeat(int repeatSeconds, long startMillis) {
        long passedMillis = System.currentTimeMillis() - startMillis;
        int repeatMillis = repeatSeconds * 1000;
        boolean repeatSecondsReached = passedMillis >= repeatMillis;

        if (repeatSeconds < 0) {
            return false;
        } else if (repeatSecondsReached) {
            return true;
        }

        long remainingMillis = repeatMillis - passedMillis;
        int remainingSeconds = (int) (remainingMillis / 1000);
        try {
            Thread.sleep(remainingMillis);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException(e);
        }

        return true;
    }

    private static int startFetching(Agenter agent, MyApplicationConfig config, MyApplicationRecord record, int pageIndex, int itemsFetched) {
        String categoryCode = config.getCategoryCode();
        List<Item> items = agent.getPageOfItems(categoryCode, pageIndex, config);

        if (items == null) {
            return itemsFetched;
        }

        int maxItems = config.getMaxItems();

        try {
            for (Item item : items) {
                String itemURL = item.getURL();

                agent.downloadItem(itemURL, config, item.getItemCount());
                itemsFetched++;

                if (maxItems > 0 && itemsFetched >= maxItems) {
                    return itemsFetched;
                }
            }
        } catch (IOException e) {
           // Log
        }

        return startFetching(agent, config, record, pageIndex + 1, itemsFetched);
    }
}

Maven 库

  • commons-cli:commons-cli:1.4
  • org.apache.logging.log4j:log4j-api:2.11.0
  • org.apache.logging.log4j:log4j-core:2.11.0
  • org.jsoup:jsoup:1.11.2

最佳答案

检查你的Agenter实现,在调用 agent.getPageOfItems 提供了 pageIndex,但可以将其存储在实例变量或类似变量中。错误本身可能是在额外的调用中它可能没有被重置(正确)。

关于Java 命令行应用程序以某种方式保留状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49814688/

相关文章:

java - Elastic APM Java-记录了事务和跨度,但未报告给Elastic APM Server或Kibana

java - 如何创建包含目标/生成源中的类的 Spring Boot fat JAR

command-line - ffmpeg 提供 key 以覆盖 m3u8 加密 key

java - 为什么我无法运行maven项目的这个jar文件?

Linux "join"命令无法正常工作?

c - 保持 C 命令行应用程序在 Mac 应用程序包中运行

Java泛型和继承

java - 如何安全地存储加密密码

java - 大数据文件的udp

java - 如何让 tomcat 看到 maven jar 而不是共享/lib 中的 jar ?