Java BufferedWriter close()

Предположим, что у меня есть следующий фрагмент кода:

operation1();
bw.close();
operation2();

Когда я звоню BufferedReader.close() Исходя из моего кода, я предполагаю, что моя JVM выполняет системный вызов, который гарантирует, что буфер был очищен и записан на диск. Я хочу знать, если close() ожидает завершения системного вызова или переходит к operation2() не дожидаясь close() заканчивать.

Перефразировать мой вопрос, когда я делаю operation2()Могу ли я предположить, что bw.close() успешно завершен?

8 ответов

Решение

могу ли я предположить, что bw.close() успешно завершил операцию action2 ()?

да

JavaDoc для java.io.BufferedReader.close() берется именно из договора, если выполняет с java.io.Reader,

Док говорит:

Закрывает поток и освобождает любые системные ресурсы, связанные с ним. Как только поток будет закрыт, дальнейшие вызовы read(), ready(), mark(), reset() или skip() вызовут IOException. Закрытие ранее закрытого потока не имеет никакого эффекта.

Хотя это не делает явного заявления о блокировке, пока файловая система не будет завершена, с этим же экземпляром BufferedReader все другие операции выдают исключение, если close() возвращается. Хотя JavaDoc можно рассматривать как неоднозначное в отношении того, когда операция завершается, если очистка и закрытие файловой системы не были завершены, когда этот метод возвращался, это нарушило бы дух контракта и было бы ошибкой в ​​Java (реализация или документация).

Закройте поток, сначала промыв его. Когда поток будет закрыт, дальнейшие вызовы write() или flush() вызовут IOException. Однако закрытие ранее закрытого потока не имеет никакого эффекта.

Хотя в документации ничего не сказано конкретно, я бы предположил, что этот вызов блокируется до завершения. На самом деле, я почти уверен, что ничего в java.io пакет неблокируемый

НЕТ! Вы не можете быть уверены по следующей причине:

BufferedWriter - это оболочка для другого писателя. Метод close() для BufferedWriter просто распространяется на базовый Writer.

Если этот лежащий в основе Writer является OutputStreamWriter, и если OutputStream является FileOutputStream, то после закрытия будет выполнен системный вызов для закрытия дескриптора файла.

Вы совершенно свободны даже для Writer, где close() является noop, или где close реализован неблокирующим, но при использовании только классов из java.io это никогда не происходит.

Writer (или же BufferedWriter) - это черный ящик, который записывает поток символов куда-то, не обязательно на диск. Вызов close() должен (по контракту метода) очистить свое буферизованное содержимое перед закрытием, и должен (обычно) блокировать, прежде чем вся его "существенная" работа будет выполнена. Но это будет зависеть от реализации и среды (например, вы не можете знать о кешах, которые находятся ниже уровня Java). Что касается работы, выполняемой самим Java-писателем (например, сделать системный вызов для записи на диск, в случае FileWriter или подобного, и закрыть дескриптор файла), да, вы можете предположить, что когда close() возвращает он уже сделал всю свою работу.

Буфер будет сброшен в операционную систему, а дескриптор файла будет закрыт, поэтому требуемые операции Java будут завершены.

НО операционная система будет кэшировать или ставить в очередь запись на фактический диск, канал, сеть, что угодно - нет никакой гарантии, что физическая запись завершена. FileChannel.force() предоставляет способ сделать это для файлов на локальных дисках: см. Javadoc.

В целом, при любой операции ввода / вывода вы не можете делать предположений о том, что произошло после write() операция завершается, даже после того, как вы close, Идея delivery является субъективным понятием относительно среды.

Например, что если writer представляет собой соединение TCP, а затем данные теряются между клиентом и сервером? Или что, если ядро ​​записывает данные на диск, но диск физически не может записать его? Или, если автор представляет почтового голубя, которого застрелят в пути?

Кроме того, представьте себе случай, когда запись не может подтвердить, что конечная точка получила данные (читай: udp/ дейтаграммы). Какой должна быть политика блокировки в этой ситуации?

Да, если вы достигнете operation2();поток должен был быть полностью закрыт. Тем не мение, close() throws IOExceptionтак что вы можете даже не добраться до operation2();, Это может или не может быть поведение, которое вы ожидаете.

Другие вопросы по тегам