Java - 为什么静态块中的方法没有及时加载?
Java - why is a method from a static block not getting loaded in time?
我编写了一个方法 processMetrics
,如果包含数据的文件自上次请求以来已更新,则加载新指标。我希望该方法每 10 秒执行一次,因此决定为此目的使用 ExecutorService
。
但是,当我测试 class 中使用配置的方法时。我可以看到调用该方法时执行程序没有从静态块加载配置。
当我 运行 未先调用注释行就进行测试时,它 returns false 因为没有更新配置。
但是当我 运行 MetricsProcessor.isMetricValid("Metric_1");
然后 assertTrue(MetricsProcessor.isMetricValid("Metric_1"))
;配置已加载且测试 returns 为真。
什么会导致这种行为?我得出的结论是,这是因为 MetricsProcessor
class 没有及时加载。这是一个有效的假设吗?
此外,我已经设法通过在执行程序之前的静态块的第一行中显式调用 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);
}
}
您面临竞争条件。有两个线程:
- 加载您的 class 然后 运行 测试
- 正在执行计划任务
在某些情况下,调度程序可能比您的测试启动得更快。但不能保证。因此,为了防止竞争条件,您至少需要确保任务的第一次执行。
这是解决方案之一:
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);
}
我编写了一个方法 processMetrics
,如果包含数据的文件自上次请求以来已更新,则加载新指标。我希望该方法每 10 秒执行一次,因此决定为此目的使用 ExecutorService
。
但是,当我测试 class 中使用配置的方法时。我可以看到调用该方法时执行程序没有从静态块加载配置。
当我 运行 未先调用注释行就进行测试时,它 returns false 因为没有更新配置。
但是当我 运行 MetricsProcessor.isMetricValid("Metric_1");
然后 assertTrue(MetricsProcessor.isMetricValid("Metric_1"))
;配置已加载且测试 returns 为真。
什么会导致这种行为?我得出的结论是,这是因为 MetricsProcessor
class 没有及时加载。这是一个有效的假设吗?
此外,我已经设法通过在执行程序之前的静态块的第一行中显式调用 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);
}
}
您面临竞争条件。有两个线程:
- 加载您的 class 然后 运行 测试
- 正在执行计划任务
在某些情况下,调度程序可能比您的测试启动得更快。但不能保证。因此,为了防止竞争条件,您至少需要确保任务的第一次执行。
这是解决方案之一:
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);
}