Зачем использовать Java AsynchronousFileChannel?

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

Любые идеи?

Ответ 1

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

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

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

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

Ответ 2

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

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

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

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

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

Ответ 3

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

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

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

  • Проблема с асинхронным чтением
  • Когда чтение завершено, выполните следующий асинхронный просмотр, а затем обработайте данные.

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

Ник

Ответ 4

Здесь что-то никто не упомянул:

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

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