Java - почему метод из статического блока не загружается вовремя? - PullRequest
0 голосов
/ 12 ноября 2018

Я написал метод processMetrics, который загружает новые метрики, если файлы, содержащие данные, были обновлены с момента последнего запроса. Я хотел, чтобы метод выполнялся каждые 10 секунд, поэтому решил использовать ExecutorService для этой цели.

Однако, когда я тестирую метод из класса, который использует конфигурацию. Я вижу, что метод вызывается без загрузки конфигурации исполнителем из статического блока. Когда я запускаю тест без предварительного вызова закомментированной строки, он возвращает 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);
            }
}

1 Ответ

0 голосов
/ 12 ноября 2018

Вы столкнулись с условиями гонки. Есть две темы:

  • загрузка вашего класса и проведение тестов
  • выполнение запланированных задач

В некоторых случаях планировщик может запускаться быстрее, чем ваши тесты. Но нет гарантии. Поэтому, чтобы предотвратить условия гонки, вам необходимо обеспечить хотя бы первое выполнение вашей задачи.

Это одно из решений:

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);
}     
...