Загрузка данных


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