Конкуренция в RandomAccessFile - PullRequest
0 голосов
/ 20 января 2019

Создайте k потоков, которые одновременно записывают в один файл символы. Первая нить записывает номер 0 в файл в строке 0 ......... Десять нитей записывает номер 9 в файл в строке 9.

Требования к реализации.

  1. Обязательно записывать каждую цифру с паузой в 1 мс!
  2. Для записи используйте класс RandomAccessFile.
  3. Разрешено использовать не более одного объекта класса RandomAccessFile!
  4. Перед началом файл, в котором будет происходить запись, должен быть удален, если он существует.
  5. Основной поток после запуска дочерних потоков для выполнения должен дождаться их завершения и затем вывести содержимое файла на консоль.

Примечание.

  1. Метод RandomAccessFile # seek (long) позволяет перемещать указатель внутри файла. Каждый поток должен знать, куда в файле записывать информацию. Поскольку в условии появляется термин «строка», вывод каждого потока должен заканчиваться ограничителем строки, который должен выводиться кроссплатформенным способом.
  2. Чтобы написать определенное число, вы можете использовать выражение «0» + n, где n - это цифра от 0 до 9 включительно. Перемещение указателя внутри файла и запись информации должны быть синхронизированы.

Я думаю, что решения моих проблем это метод поиска в RandomAccessFile, но я не знаю, как его использовать.

public final class Part5 {
    private static final List<Thread> threadList = new ArrayList<>();
    private static AtomicInteger pos = new AtomicInteger(0);
    private static final String FILE_NAME = "part5.txt";

    private Part5() {
    }

    public static void main(String[] args) throws InterruptedException {
        run();
    }

    public static void run() throws InterruptedException {
        try {
            final RandomAccessFile accessFile = new RandomAccessFile(FILE_NAME, "rw");
            for (int i = 0; i < 10; i++) {
                Thread thread = new Thread(new RandomThread(accessFile, new AtomicInteger(i), pos));
                threadList.add(thread);
                thread.start();
                pos.getAndAdd(20);
            }

            for (Thread thread : threadList) {
                thread.join();
            }
        } catch (FileNotFoundException e) {
            System.err.println(e.getMessage());
        }
    }
}

class RandomThread implements Runnable {
    private final RandomAccessFile accessFile;
    private AtomicInteger number;
    private AtomicInteger pos;

    public RandomThread(RandomAccessFile accessFile, AtomicInteger number, AtomicInteger pos) {
        this.accessFile = accessFile;
        this.number = number;
        this.pos = pos;
    }

    @Override
    public synchronized void run() {
        synchronized (accessFile) {
            try {
                for (int i = 0; i < 20; i++) {
//                    accessFile.seek(pos.getAndIncrement());
                    accessFile.writeBytes(number.toString());
                    Thread.sleep(1);
                }
                accessFile.write(System.lineSeparator().getBytes());
                Thread.currentThread().interrupt();
            } catch (IOException | InterruptedException e) {
                System.err.println(e.getMessage());
            }
        }
    }
}

public final class Part5 {
    private static final List<Thread> threadList = new ArrayList<>();
    private static AtomicInteger pos = new AtomicInteger(0);
    private static final String FILE_NAME = "part5.txt";

    private Part5() {
    }

    public static void main(String[] args) throws InterruptedException {
        run();
    }

    public static void run() throws InterruptedException {
        try {
            final RandomAccessFile accessFile = new RandomAccessFile(FILE_NAME, "rw");
            for (int i = 0; i < 10; i++) {
                Thread thread = new Thread(new RandomThread(accessFile, new AtomicInteger(i), pos));
                threadList.add(thread);
                thread.start();
                pos.getAndAdd(20);
            }

            for (Thread thread : threadList) {
                thread.join();
            }
        } catch (FileNotFoundException e) {
            System.err.println(e.getMessage());
        }
    }
}

class RandomThread implements Runnable {
    private final RandomAccessFile accessFile;
    private AtomicInteger number;
    private AtomicInteger pos;

    public RandomThread(RandomAccessFile accessFile, AtomicInteger number, AtomicInteger pos) {
        this.accessFile = accessFile;
        this.number = number;
        this.pos = pos;
    }

    @Override
    public synchronized void run() {
        synchronized (accessFile) {
            try {
                for (int i = 0; i < 20; i++) {
//                    accessFile.seek(pos.getAndIncrement());
                    accessFile.writeBytes(number.toString());
                    Thread.sleep(1);
                }
                accessFile.write(System.lineSeparator().getBytes());
                Thread.currentThread().interrupt();
            } catch (IOException | InterruptedException e) {
                System.err.println(e.getMessage());
            }
        }
    }
}

Вывод в файл

00000000000000000000
99999999999999999999
88888888888888888888
77777777777777777777
66666666666666666666
55555555555555555555
44444444444444444444
33333333333333333333
22222222222222222222
11111111111111111111

Но я жду

00000000000000000000
11111111111111111111
22222222222222222222
33333333333333333333
44444444444444444444
55555555555555555555
66666666666666666666
77777777777777777777
88888888888888888888
99999999999999999999
...