import java.io.FileOutputStream;
import java.io.IOException;
/**
* Первый поток. Посимвольно записывает в файл
* {@link FileHelper#FILE_NAME} строку
* {@code "the first thread writes the time:"} с задержкой 200 мс
* между символами, затем дописывает текущее время.
* После записи спит 1 секунду.
* <p>
* Весь блок записи (строка + время) выполняется внутри
* {@code synchronized (FileHelper.MONITOR)}, поэтому второй поток
* не может переименовать файл во время записи.
* </p>
*
* @author Student
* @version 1.0
*/
public class WriterThread extends Thread {
/** Записываемая строка. */
private static final String LINE = "the first thread writes the time:";
/** Флаг работы потока; {@code volatile} — виден всем потокам сразу. */
private volatile boolean running = true;
/**
* Создаёт поток с именем {@code WriterThread}.
*/
public WriterThread() {
super("WriterThread");
}
/**
* Требует остановки потока.
* Прерывает его даже во время сна через {@link Thread#interrupt()}.
*/
public void stopThread() {
running = false;
this.interrupt();
}
/**
* Основной цикл потока.
* Обрабатывает {@link IOException} при работе с файлами и
* {@link InterruptedException} при прерывании сна.
*/
@Override
public void run() {
while (running && !isInterrupted()) {
// Критическая секция — запись строки и времени
synchronized (FileHelper.MONITOR) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream(FileHelper.FILE_NAME, true);
// Посимвольная запись строки
for (int i = 0; i < LINE.length(); i++) {
if (!running) return;
fos.write(LINE.charAt(i));
fos.flush();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
}
// Дописываем время
String timeStr = FileHelper.currentTime()
+ System.lineSeparator();
fos.write(timeStr.getBytes());
fos.flush();
} catch (IOException e) {
System.err.println("[Writer] Ошибка записи в файл: "
+ e.getMessage());
} finally {
// Закрываем поток вручную (без try-with-resources,
// чтобы показать обработку IOException при close)
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
System.err.println("[Writer] Ошибка закрытия файла: "
+ e.getMessage());
}
}
}
} // конец synchronized — монитор освобождён
// Сон 1 секунда вне критической секции
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
}
}
}