Следует ли использовать Thread.sleep при чтении из FIFO?
В связи с тем, что почти в каждом вопросе, касающемся использования Thread.sleep, в основном указывается на его использование только в определенных ситуациях, я пришел спросить вас, правильно ли использовать его в моем случае или есть ли лучший способ сделать это.
Операционная система - Linux(Debian), в которой запущен скрипт bash, который определяет, когда устройство (в частности, устройство хранения) вставляется / удаляется, а затем записывает в FIFO строку с типом "ADD {путь". -to-dev}"или"REM {path-to-dev}".
Я создал небольшое приложение в Java, которое использует два потока. Первый поток вызовет метод read, который анализирует String для стандартного вывода, после чего он будет ждать (). Второй поток проверит, является ли FIFO пустым или нет, и затем, когда он увидит, что строка была вставлена, он вызовет notify(), так что другой поток напечатает строку там и так далее. Внутри цикла, где он проверяет, есть ли у FIFO данные или нет, я вызываю Thread.sleep(1000), и я не уверен, является ли это хорошим подходом или нет. Я представлю код, который обрабатывает все действия.
Во-первых, класс, который имеет методы чтения:
public class Detect {
private File file;
private BufferedReader read;
private volatile boolean readable;
private static String readFromFile;
public Detect() throws FileNotFoundException {
file = new File("/hardware_stuff/hardware_events");
read = new BufferedReader(new FileReader(file));
readable = true;
}
synchronized String readFromFifo() {
while (!readable) {
try {
wait();
} catch (InterruptedException ex) {
System.out.println("Interrupted during the wait for read.");
}
}
try {
while (read.ready()) {
readFromFile = read.readLine();
}
} catch (IOException ex) {
System.out.println("Error in reading from FIFO.");
}
readable = false;
notify();
return readFromFile;
}
synchronized void waitForFifo() {
while (readable) {
try {
wait();
} catch (InterruptedException ex) {
Logger.getLogger(Detect.class.getName()).log(Level.SEVERE, null, ex);
}
}
try {
while (!read.ready()) {
Thread.sleep(1000);
System.out.println("Sleeping due to lack of activity in FIFO in thread : " + Thread.currentThread().getName());
}
} catch (IOException | InterruptedException ex) {
Logger.getLogger(Detect.class.getName()).log(Level.SEVERE, null, ex);
}
readable = true;
notify();
}}
Далее ветка, которая будет читать с него.
public class ReadThread extends Thread {
Detect detect;
private boolean shouldBeRunning;
public ReadThread(Detect detect) {
this.detect = detect;
shouldBeRunning = true;
}
@Override
public void run() {
while (shouldBeRunning) {
String added = detect.readFromFifo();
System.out.println(added);
}
}
public void stopRunning() {
shouldBeRunning = false;
}}
Наконец, поток, который проверит, пуст ли FIFO или нет.
public class NotifyThread extends Thread {
Detect detect;
private boolean shouldBeRunning;
public NotifyThread(Detect detect) {
this.detect = detect;
shouldBeRunning = true;
}
@Override
public void run() {
while (shouldBeRunning) {
detect.waitForFifo();
}
}
public void stopRunning() {
shouldBeRunning = false;
}}
В основном я просто создаю темы и запускаю их.
Detect detect = new Detect();
NotifyThread nThread = new NotifyThread(detect);
ReadThread rThread = new ReadThread(detect);
nThread.start();
System.out.println("Started the notifier thread in : " + Thread.currentThread().getName());
rThread.start();
System.out.println("Started the reading thread in : " + Thread.currentThread().getName());
Есть ли альтернатива вызову сна или другой подход, который я могу использовать, чтобы заменить сон чем-то другим? Я уже читал другие вопросы, связанные с этой темой, и я все еще не уверен / не понял, показан ли этот вид случая для сна или нет.
ОБНОВЛЕНИЕ: Как сказал @james Large, не было необходимости опрашивать на предмет готовности. Я не знал, что если нет строки, readLine() будет "спать", и нет необходимости опрашивать его. Я удалил поток уведомлений и просто сохранил ReadThread, который вызовет метод Detect readFromFifo(), и все это работает хорошо. @dumptruckman, спасибо за предложение. Хотя это не относится к моему делу, я не знал о WatchService, и это было хорошее чтение, хорошие вещи, которые нужно знать. @Nyamiou Galeanthrope, таймер был бы полезен, но, как я уже сказал, я оставляю только один поток для выполнения того же метода, и он работает как задумано.@Krzysztof Cichocki, спасибо за указание на наличие проблем. Я знал об этом, иначе я бы не задавал этот вопрос.