Зачем использовать Java AsynchronousFileChannel? - PullRequest
12 голосов
/ 04 мая 2010

Я могу понять, почему сетевые приложения используют мультиплексирование (чтобы не создавать слишком много потоков), и почему программы используют асинхронные вызовы для конвейерной передачи (более эффективно). Но я не понимаю цели эффективности AsynchronousFileChannel.

Есть идеи?

Ответы [ 4 ]

8 голосов
/ 04 мая 2010

Это канал, который вы можете использовать для асинхронного чтения файлов, т.е. операции ввода-вывода выполняются в отдельном потоке, так что поток, из которого вы его вызываете, может выполнять другие действия во время выполнения операций ввода-вывода. .

Например: методы read() класса возвращают объект Future, чтобы получить результат чтения данных из файла. Таким образом, вы можете вызвать read(), который немедленно вернется с объектом Future. В фоновом режиме другой поток будет читать фактические данные из файла. Ваш собственный поток может продолжать что-то делать, и когда ему нужны данные для чтения, вы вызываете get() для объекта Future. Затем он вернет данные (если фоновый поток не завершил чтение данных, он заблокирует ваш поток, пока данные не будут готовы). Преимущество этого в том, что вашему потоку не нужно ждать всю длину операции чтения; он может делать некоторые другие вещи, пока ему действительно не нужны данные.

См. документацию .

Обратите внимание, что AsynchronousFileChannel будет новым классом в Java SE 7, который еще не выпущен.

3 голосов
/ 28 июля 2015

Основная причина, по которой я могу использовать асинхронный ввод-вывод, заключается в том, чтобы лучше использовать процессор. Представьте, что у вас есть приложение, которое выполняет какую-то обработку файла. А также давайте предположим, что вы можете обрабатывать данные, содержащиеся в файле, кусками. Если вы не используете асинхронный ввод-вывод, ваше приложение, вероятно, будет вести себя примерно так:

  1. Считать блок данных. На данный момент загрузка процессора не требуется, поскольку вы заблокированы в ожидании чтения данных.
  2. обработать данные, которые вы только что прочитали. В этот момент ваше приложение начнет использовать циклы ЦП, поскольку оно обрабатывает данные.
  3. Если читать больше данных, перейдите к # 1.

Загрузка процессора будет увеличиваться, а затем возрастать до нуля, а затем увеличиваться, а затем до нуля, .... В идеале вы хотите не сидеть сложа руки, если хотите, чтобы ваше приложение работало эффективно и обрабатывало данные максимально быстро. Лучший подход был бы:

  1. Асинхронное чтение проблемы
  2. Когда чтение завершается, выдает следующее асинхронное чтение и затем обрабатывает данные

Первый шаг - начальная загрузка. У вас еще нет данных, поэтому вы должны выполнить чтение. С тех пор, когда вы получаете уведомление о завершении чтения, вы выполняете еще одно асинхронное чтение, а затем обрабатываете данные. Преимущество здесь состоит в том, что к тому времени, когда вы закончите обработку фрагмента данных, следующее чтение, вероятно, закончится, так что у вас всегда будут данные для обработки и, следовательно, вы будете более эффективно использовать процессор. Если ваша обработка заканчивается до завершения чтения, вам может потребоваться выполнить несколько асинхронных операций чтения, чтобы у вас было больше данных для обработки.

Ник

3 голосов
/ 15 февраля 2012

Я только что натолкнулся на другую, несколько неожиданную причину использования AsynchronousFileChannel. При выполнении произвольной записи, ориентированной на запись, для больших файлов (превышение физической памяти, поэтому кеширование не помогает всем) в NTFS, я обнаружил, что AsynchronousFileChannel выполняет в два раза больше операций в однопоточном режиме, чем обычный FileChannel.

Мое лучшее предположение состоит в том, что поскольку асинхронный ввод-вывод сводится к перекрывающемуся вводу-выводу в Windows 7, драйвер файловой системы NTFS может обновлять свои собственные внутренние структуры быстрее, когда ему не нужно создавать точку синхронизации после каждого вызова.

Я провел микро-бенчмаркинг с RandomAccessFile, чтобы посмотреть, как он будет работать (результаты очень близки к FileChannel, и все же половина производительности AsynchronousFileChannel.

Не уверен, что происходит с многопоточными записями. Это на Java 7, на SSD (SSD на порядок быстрее магнитного, и еще на порядок быстрее для небольших файлов, которые помещаются в память).

Будет интересно посмотреть, сохранятся ли те же соотношения в Linux.

1 голос
/ 22 февраля 2017

Вот то, что никто не упомянул:

Обычный FileChannel (поскольку он реализует InterruptibleChannel), а также все, что его использует, например OutputStream, возвращаемое Files.newOutputStream(), имеет неудачное поведение [1] [2] , при котором любая операция блокировки (например, read() и write()) в потоке в прерванном состоянии приведет к закрытию самого Channel с java.nio.channels.ClosedByInterruptException.

Когда это проблема, вместо нее можно использовать AsynchronousFileChannel.

...