У меня есть этот кусок кода.
// 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:
Это все еще не минимальный воспроизводимый пример — это не то, что мы можем скомпилировать и запустить.
Пожалуйста, проверьте ссылку, которая находится в комментарии @JonSkeet и в моем, так как она объясняет, что мы просим и почему ее создание может помочь вам 1) получить ответ здесь или 2) более легко обнаружить источник проблемы самостоятельно
Похоже, вы используете бесконечный замкнутый цикл для постоянного опроса свойств — почему?
@HovercraftFullOfEels Мне нужно обновлять updateRate всякий раз, когда в файле есть изменения - я не мог придумать что-то другое
Я не очень хорошо знаком с использованием WatchService, но в большинстве примеров, которые я видел (например), WatchKey назначается внутри циклу с использованием метода .take(). Это похоже на метод блокировки, поэтому он выполняется в фоновом потоке. Я думаю, что это заблокирует цикл до тех пор, пока не произойдет изменение, предотвращая ненужное воровство циклов ЦП.
Я отредактировал код так, что я беру ключ внутри цикла. Я получаю точно такой же результат.




Может случиться так, что 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. Спасибо.
Если бы вы смогли сократить свой код и ошибку до разумного минимальный воспроизводимый пример, вы, вероятно, увеличили бы свои шансы быстро получить достойный ответ.