Java——为什么静态块中的方法没有及时加载



我编写了一个方法processMetrics,如果包含数据的文件自上次请求以来更新,该方法将加载新的度量。我希望该方法每10秒执行一次,因此决定使用ExecutorService

但是,当我在使用config。我可以看到,该方法是在执行器没有从静态块加载配置的情况下调用的。当我在没有首先调用注释行的情况下运行测试时,由于没有更新任何配置,它返回false。但是当我运行MetricsProcessor.isMetricValid("Metric_1");然后运行assertTrue(MetricsProcessor.isMetricValid("Metric_1"))时;配置被加载,测试返回true。

是什么导致了这种行为?我得出的结论是,这是因为MetricsProcessor类没有及时加载。这是一个有效的假设吗?

此外,我通过在executor之前的静态块的第一行显式调用processMetrics();,成功地解决了这个问题。但仍然不清楚为什么会发生这种情况?

@Test
public void testIsMetricValid() {
//        MetricsProcessor.isMetricValid("Metric_1");
assertTrue(MetricsProcessor.isMetricValid("Metric_1"));
}

// MetricsProcessor is a final class
private static Runnable loadMetrics = MetricsProcessor::processMetrics;
private static ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
static {
executor.scheduleAtFixedRate(processMetrics, 0, 10, TimeUnit.SECONDS);
}
private static void processMetrics() {
{
long metricsLastMod = metricsFile.lastModified();
if (metricsLastMod > lastMod.get()) {
processMetricsData(metricsFile);
lastMod.set(metricsLastMod);
}
}

您正面临比赛条件。有两个线程:

  • 加载类,然后运行测试
  • 执行计划任务

在某些情况下,调度程序的启动速度可能比您的测试更快。但这并不能保证。因此,为了防止比赛条件,你需要确保至少第一次执行你的任务。

这是解决方案之一:

private static Runnable loadMetrics = MetricsProcessor::processMetrics;
private static ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
static {
loadMetrics.run();
// Note the updated initial delay. 
executor.scheduleAtFixedRate(loadMetrics, 10, 10, TimeUnit.SECONDS);
}     

最新更新