Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
56_Java.pdf
Скачиваний:
211
Добавлен:
18.02.2016
Размер:
2.39 Mб
Скачать

Скачано с сайта http://ivc.clan.su

Буферизированные потоки

Классы семейства Buffered, как и классы фильтрованных потоков, являются надстройками. Однако Buffered-потоки никакого изменения данных основного потока не выполняют. Они обеспечивают присоединение к основному потоку (приемнику или источнику данных) буфера (области в памяти).

Буферизация позволяет избежать необходимости обращения к источнику или приемнику при выполнении каждой отдельной операции read или write. Классы Buffered рекомендуется использовать совместно с потоками семейства File. Буферизация обеспечивает уменьшение числа обращений к дисковой памяти, что повышает скорость выполнения операций ввода-вывода.

В каждом Buffered-классе имеется два конструктора: один в качестве параметров принимает ссылку на объект основного потока (источника или приемника данных) и значение размера буфера, другому конструктору в качестве параметра передается только ссылка на объект потока (размер буфера устанавливается по умолчанию).

Принципы работы Buffered-потоков

Входные потоки

Для ввода (чтения) из потока вызывается его метод read. Если при выполнении read выясняется,

что буфер потока пуст:

1)вызывается одноименный метод (т.е. read) основного потока-источника данных;

2)буфер заполняется максимально возможной порцией данных (это или размер буфера, или объем данных источника);

3)запрошенные данные извлекаются из буфера;

При очередном обращении к буферизированному потоку данные будут извлекаться из буфера, пока его содержимое не будет исчерпано, после чего объект буферизированного потока вновь будет вынужден вызвать метод read потока-источника и т.д.

Выходные потоки

Запись в буферизированный поток осуществляется методом write. Когда буфер данных заполняется, вызывается write основного потока-приемника, который освобождает буфер и т.д.

Такой механизм позволяет превратить последовательность запросов на вывод (или запись) небольших порций данных в поток-буфер в единственный вызов метода write потока-приемника.

Метод flush осуществляет сброс потока, т.е. вывод (запись) всех данных из буфера в потокприемник вызовом его метода write.

Пример: буферизированный поток вывода в файл

BufferedOutputStream out =

new BufferedOutputStream(new FileOutputStream(path));

Канальные потоки

Классы Piped позволяют связывать входные и выходные потоки данных и получать канальные потоки.

Канальные потоки используются в виде пар:

поток ввода — поток вывода (PipedlnputStream PipedOutputStream);

поток чтения — поток записи (PipedReader PipedWriter).

Данные, переданные в выходной поток (вывода или записи) служат источником для входного потока (ввода или чтения).

44

Скачано с сайта http://ivc.clan.su

С каналом (pipe), т.е. парой потоков, связан общий внутренний буфер, емкость которого определена при реализации класса (не существует средств динамического управления размером буфера).

Каналы реализуют механизм обмена данными между различными потоками вычислений (threads). При этом корректный способ работы с каналом предполагает использование двух потоков вычислений: один из них осуществляет вывод данных в выходной поток канала, другой — ввод из

входного потока канала (см. пример PipeDemo.java).

В примере PipeDemo.java Piped-потоки связываются при их создании, но это можно сделать и позже, так как в составе классов Piped имеются конструкторы без параметров. Для соединения канальных потоков имеется метод connect. Попытки использования канальных потоков до их соединения или связывание ранее соединенных потоков приводят к выбрасыванию исключения

IOException.

Синхронизация потоков данных

Синхронизация — это механизм, применяемый в многопоточном программировании и обеспечивающий корректную работу различных потоков вычисления с разделяемыми ресурсами.

Разделяемый ресурс потоков используется потоком вычислений только после захвата права на блокировку объекта. При этом другие потоки не могут использовать объект, пока блокировка не будет освобождена.

Классы символьных и байтовых потоков придерживаются определенной политики синхронизации.

1)Для байтовых потоков

Классы байтовых потоков обеспечивают синхронизацию текущего объекта потока данных при

выполнении (в рамках определенного потока вычислений) операций типа read, write, которые не должны прерываться воздействием со стороны других потоков вычисления (threads).

Это позволяет нескольким потокам вычислений успешно использовать один и тот же поток данных.

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

Аналогично, если два потока thread выполняют вывод в один и тот же поток данных, то байты от каждого потока thread размещаются в потоке данных в виде непрерывных последовательностей, не перемежаемых байтами от другого потока вычислений.

2)Для символьных потоков (более гибкий подход)

Символьные потоки выполняют синхронизацию protected-поля lock объекта потока. В этом поле

хранится ссылка (this) на объект потока как таковой (таким образом, синхронизируется сам объект потока данных).

В классах Reader и Writer предусмотрен, кроме того, protected-конструктор, в качестве параметра получающий объект, ссылка на который будет сохранена в поле lock создаваемого объекта потока данных. В объектах некоторых производных классов поле lock ссылается не на собственный объект (this), а на другой объект, который реально синхронизируется при выполнении операций ввода/вывода.

Например, в объекте класса StringWriter, выполняющего запись символов в объект StringBuffer, поле lock хранит ссылку на объект StringBuffer.

45

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]