我编写了一种方法processMetrics
,如果包含数据的文件自上次请求以来已更新,则该方法将加载新指标。我希望该方法每10秒执行一次,因此决定为此目的使用ExecutorService
。
但是,当我从使用config的类中测试方法时。我可以看到在没有执行者从静态块加载配置的情况下调用了该方法。
当我在不首先调用注释行的情况下运行测试时,由于未更新任何配置,它会返回false。
但是当我先运行MetricsProcessor.isMetricValid("Metric_1");
然后运行assertTrue(MetricsProcessor.isMetricValid("Metric_1"))
时;配置已加载,测试返回true。
什么可能导致这种行为?我得出一个结论,这是因为MetricsProcessor
类没有及时加载。这是一个有效的假设吗?
此外,我设法通过在执行程序之前的静态块第一行中显式调用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);
}
}
答案 0 :(得分:1)
您正面临比赛条件。有两个线程:
在某些情况下,调度程序的启动速度可能比您的测试更快。但是并不能保证。因此,为了防止出现竞争状况,您需要至少确保首次执行任务。
这是解决方案之一:
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);
}