Ошибка класса свойств Java

У меня есть этот кусок кода.

// On a thread
try {
    WatchService watcher = FileSystems.getDefault().newWatchService();
    Path directory = Paths.get("properties");
    WatchKey watchKey = directory.register(watcher, StandardWatchEventKinds.ENTRY_MODIFY);
    while (true) {
        for (WatchEvent<?> event : watchKey.pollEvents()) {
            Path changed = (Path) event.context();
            if (changed.toString().equals("radar.properties")) {
                System.out.println("read call:");
                readProperties();
            }

        }

        if (!watchKey.reset()) {
            break;
        }
    }
} catch (IOException e) {
    FCSLogger.LOGGER.log(Level.SEVERE, "Exception while setting up WatchService", e);
}

// Method called by the above code

private void readProperties() {
    try {
        InputStream input = new FileInputStream(Paths.get("properties", "radar.properties").toString());
        Properties prop = new Properties();
        prop.load(input);
        updateRate = Integer.parseInt(prop.getProperty("updateRate"));
        System.out.println(updateRate);
        input.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Он возвращает правильный результат при первом вызове, а затем блокирует весь поток. Я выделил ошибку именно в этом методе, так как все остальное работает без нареканий, когда этот метод не вызывается. Мне интересно, что я делаю неправильно здесь. Снимок вывода консоли:

// First change of file:
read call:
10
read call:
10

// Second change of file:
read call:

// I keep changing but nothing happens:

Если бы вы смогли сократить свой код и ошибку до разумного минимальный воспроизводимый пример, вы, вероятно, увеличили бы свои шансы быстро получить достойный ответ.

Hovercraft Full Of Eels 01.06.2019 15:00

Это все еще не минимальный воспроизводимый пример — это не то, что мы можем скомпилировать и запустить.

Jon Skeet 01.06.2019 15:08

Пожалуйста, проверьте ссылку, которая находится в комментарии @JonSkeet и в моем, так как она объясняет, что мы просим и почему ее создание может помочь вам 1) получить ответ здесь или 2) более легко обнаружить источник проблемы самостоятельно

Hovercraft Full Of Eels 01.06.2019 15:09

Похоже, вы используете бесконечный замкнутый цикл для постоянного опроса свойств — почему?

Hovercraft Full Of Eels 01.06.2019 15:14

@HovercraftFullOfEels Мне нужно обновлять updateRate всякий раз, когда в файле есть изменения - я не мог придумать что-то другое

ssmiljanic 01.06.2019 15:16

Я не очень хорошо знаком с использованием WatchService, но в большинстве примеров, которые я видел (например), WatchKey назначается внутри циклу с использованием метода .take(). Это похоже на метод блокировки, поэтому он выполняется в фоновом потоке. Я думаю, что это заблокирует цикл до тех пор, пока не произойдет изменение, предотвращая ненужное воровство циклов ЦП.

Hovercraft Full Of Eels 01.06.2019 15:27

Я отредактировал код так, что я беру ключ внутри цикла. Я получаю точно такой же результат.

ssmiljanic 01.06.2019 15:39
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
7
83
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Может случиться так, что readProperties бросит NumberFormatException, и это приведет к выходу вашего потока наблюдателя.

Вы можете оборачивать вызовы в readProperties и перехватывать исключения; так что, по крайней мере, наблюдатель будет продолжать наблюдать в случае исключений.

И вы должны использовать take, чтобы поток наблюдателя заблокировался. Ваше текущее решение вызывает 100% загрузку процессора.

См. ниже измененный код. Я добавил поток записи для обновления файла, и (что неудивительно?) readProperties может завершиться ошибкой, поскольку мы обращаемся к файлу во время его записи. Возможный вывод:

....
property=5000
property=null
java.lang.NumberFormatException: null
  at java.base/java.lang.Integer.parseInt(Integer.java:614)
  at java.base/java.lang.Integer.parseInt(Integer.java:770)
  at cl.ClientPoll.readProperties(ClientPoll.java:26)
  at cl.ClientPoll.run(ClientPoll.java:46)
property=6000
property=7000
....

Так что при просмотре вы можете: пропустить ошибку и продолжить; или используйте другие API, чтобы записываемый файл был заблокирован во время записи.


Образец кода

package cl;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.Properties;

public class ClientPoll extends Thread {
  private void readProperties() {
    try {
      Path path = Paths.get("radar.properties");
      InputStream input =new FileInputStream(path.toString());
      Properties prop = new Properties();
      prop.load(input);
      String property = prop.getProperty("updateRate");
      System.out.println("property = "+property);
      int updateRate = Integer.parseInt(property);
//      System.out.println(updateRate);
      input.close();
    } catch (IOException e) {
      e.printStackTrace(System.out);
    }
  }

  @Override
  public void run() {
    try {
      WatchService watcher = FileSystems.getDefault().newWatchService();
      Path directory = Paths.get(".");
      WatchKey watchKey = directory.register(watcher, StandardWatchEventKinds.ENTRY_MODIFY);
      while (true) {
        WatchKey wk = watcher.take();
        for (WatchEvent<?> event : wk.pollEvents()) {
          Path changed = (Path) event.context();
          if (changed.toString().equals("radar.properties")) {
            try {
              readProperties();
            } catch (Exception e) {
              e.printStackTrace(System.out);
            }
          }
        }
        if (!watchKey.reset()) {
          break;
        }
      }
    } catch (IOException e) {
      e.printStackTrace(System.out);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }

  public static void main(String[] args) {
    new ClientPoll().start();
    new Writer().start();
  }
}

class Writer extends Thread {
  @Override
  public void run() {
    try {
      for (int i=0;i<10;i++) {
        File f = new File("radar.properties");
        FileWriter fw = new FileWriter(f);
        fw.write("updateRate = "+i*1000);
        fw.close();
        sleep(1000L);
      }
    } catch (Exception e) {
      e.printStackTrace(System.out);
    }
    System.out.println("exit");
    System.exit(0);
  }
}

Это было NumberFormatException в checkProperties. Спасибо.

ssmiljanic 01.06.2019 15:57

Другие вопросы по теме