2013-08-04 1 views
7

Я использую потоки много раз, но я никогда не читал много о том, как они на самом деле работают. Я также не знаю много о них, кроме того, что поток - это всего лишь метафора. Поток представляет только последовательность байтов. Я не знаю много о том, как они на самом деле работают, я предполагаю, что открытие потока файлов в Java взаимодействует с ОС, которые имеют функциональность, чтобы дать «указатель» на поток.Как потоки в Java влияют на потребление памяти?

В основном, мой вопрос заключается в том, как потоки влияют на потребление памяти. Когда у вас есть, например, поток ввода и вы начинаете читать с него, вы только начинаете увеличивать потребление памяти с количеством прочитанных байтов? При открытии потока в Java вы фактически не загружаете полный файл перед началом чтения? Если вы читаете из одного потока и напрямую пишете в другой поток, вы увеличиваете объем памяти только с объемом прочитанных байтов (и, возможно, в буфере)? Если вы читаете байты в байтовый массив в java, то вы увеличиваете потребление памяти с размером файла?

Может показаться странным вопросом, но мне может понадобиться какое-то руководство/исправление в моем понимании. Благодарю.

+0

У вас есть очень хорошее объяснение [здесь] (http://www.ibm.com/developerworks/library/j-zerocopy/index.html) нулевой копии. Также он объясняет использование буферов и памяти. –

ответ

3

Существует почти нет накладных расходов памяти после начала чтения от InputStream. Для открытия файла очень мало OS-накладных расходов и крошечных накладных расходов в JVM для нового размещения объектов. Также могут возникнуть небольшие накладные расходы, если вы используете BufferedInputStream, который по умолчанию составляет 8 КБ.

Накладные расходы для написания очень сильно зависят от того, где вы пишете. Если это FileOutputStream, то это то же, что описано выше. Если это ByteArrayOutputStream, то в лучшем случае это (длина потока 2 * длины) и (длина длины 3 *) байтов в худшем случае. То есть для копирования 10k байтов из InputStream в массив байтов 30k байт будет выделен в худшем случае.

Причина этого заключается в том, что размер роста увеличивается в 2 раза после достижения его предела, а также вызывается новый буфер, когда вы вызываете toByteArray().

5

Все ответы выше - отличные ответы, но я не верю, что они отвечают на ваш первоначальный вопрос о потреблении памяти.

В Java вы можете просматривать потоки несколькими способами. Сначала у вас есть Raw-потоки, которые являются потоком самого низкого уровня и взаимодействуют с базовой ОС (File, Network и т. Д.) С минимальными издержками памяти. Во-вторых, это буферизованные потоки, которые можно использовать для обертывания необработанного потока и добавления некоторой буферизации и значительного повышения производительности. Буферизация потоков добавляет фиксированный объем служебных данных памяти для буферизации и может быть установлен вашим приложением. Не уверен, что такое дефолт, но это, вероятно, что-то минимальное, такое как 32K.

Третий тип потока - это поток памяти (то есть ByteArrayInput/Ouput), они используют столько памяти, сколько вы им пишете, и будете расти по мере необходимости, а не избавляться от их памяти, пока счетчик ссылок не достигнет нуля (они больше не используется). Эти потоки очень полезны, но, очевидно, могут потреблять много памяти.

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

Смежные вопросы