Можете ли вы объяснить концепцию потоков?


Я понимаю, что поток-это представление последовательности байтов. Каждый поток предоставляет средства для чтения и записи байтов в заданное резервное хранилище. Но в чем смысл этого потока? Почему сам резервный магазин не является тем, с чем мы взаимодействуем?

по какой-то причине эта концепция просто не щелкает для меня. Я прочитал кучу статей, но я думаю, что мне нужна аналогия или что-то в этом роде.

15 169

15 ответов:

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

давайте забудем о запасном хранилище на некоторое время и начнем думать об аналогии с потоком воды. Вы получаете непрерывный поток данных, точно так же, как вода непрерывно течет в реке. Вы не обязательно знаете, откуда берутся данные, и чаще всего вам это не нужно; будь то из файла, сокета или любого другого источника, это не имеет (не должно) особого значения. Это очень похоже на получение потока воды, в результате чего вам не нужно знать, откуда он исходит; будь то из озера, фонтана или любого другого источника, это не имеет (не должно) действительно значения.

int ReadInt(StreamReader reader) { return Int32.Parse(reader.ReadLine()); }

// in another method:
Stream fileStream = new FileStream("My Data.dat");
Stream zipStream = new ZipDecompressorStream(fileStream);
Stream decryptedStream = new DecryptionStream(zipStream);
StreamReader reader = new StreamReader(decryptedStream);

int x = ReadInt(reader);

как вы видите, это становится очень легко изменить источник входного сигнала без изменения логики обработки. Например, для чтения данных из сетевого сокета вместо файл:

Stream stream = new NetworkStream(mySocket);
StreamReader reader = new StreamReader(stream);
int x = ReadInt(reader);

так просто, как это может быть. И красота продолжается, так как вы можете использовать любой источник ввода, пока вы можете построить поток "обертку" для него. Вы даже можете сделать это:

public class RandomNumbersStreamReader : StreamReader {
    private Random random = new Random();

    public String ReadLine() { return random.Next().ToString(); }
}

// and to call it:
int x = ReadInt(new RandomNumbersStreamReader());

посмотреть? Как долго, как ваш метод не заботится о том, что такое источник ввода, вы можете настроить свой источник различными способами. Абстракция позволяет очень элегантно отделить ввод от логики обработки.

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

дело в том, что вам не нужно знать, что такое резервное хранилище - это абстракция над ним. В самом деле, там может даже не быть резервное хранилище-вы можете читать из сети, и данные никогда не "хранятся" вообще.

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

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

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

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

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

файлы по большей части неинтересны, потому что потоки не делают много выше и за пределами того, с чем я знаком с непотоковыми методами. Давайте начнем с Интернет-файлов.

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

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

таким образом, потоки облегчают ввод-вывод. Вы, конечно, можете написать класс TcpFileDownloader, который делает то, что делает поток, но тогда у вас есть класс, специфичный для TCP. Большинство потоковых интерфейсов просто предоставляют метод Read() и Write (), А любые более сложные концепции обрабатываются внутренней реализацией. Из-за этого вы можете использовать один и тот же базовый код для чтения или записи в память, файлы на диске, сокеты и многие другие хранилища данных.

Это просто концепция, еще один уровень абстракции, который делает вашу жизнь проще. И все они имеют общий интерфейс, который означает, что вы можете объединить их в трубе, как способ. Например, кодируйте в base64, затем zip, а затем запишите это на диск и все в одной строке!

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

во-первых, это упрощает сами компоненты: если вы хотите положить шоколадную глазурь на торт, вам не нужно сложное устройство, которое знает все о тортах, вы можете создать немое устройство, которое наклеивает шоколадную глазурь на все, что в него подается (в мультфильмах это доходит до того, что не знает, что следующий элемент в этом не торт, это хитрый E. Coyote).

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

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

лучшее объяснение потоков, которые я видел, это Глава 3 SICP. (Возможно, вам придется прочитать первые 2 Главы, чтобы это имело смысл, но вы все равно должны. : -)

Они вообще не используют sterams для байтов, а скорее целые числа. Большие моменты, которые я получил от него были:

  • потоки задерживаются списки
  • вычислительные накладные расходы [нетерпеливо вычисляя все заранее, в некоторых случаях] возмутительно
  • мы можем используйте потоки для представления бесконечно длинных последовательностей

в информатике поток-это непрерывный поток информации.

когда я думаю о потоковой передаче, я думаю о видео сервис доставки данных. Хотя потоковое видео. Текст, аудио, zip файлы могут быть переданы тоже. Кроме того, потоковая передача не ограничивается файлами. HTTP, FTP, SSH-соединения и Вход/Выход также могут быть потоковыми.

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

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

прогрессивная загрузка позволяет просматривать видеофайл по мере его загрузки. Возможна быстрая перемотка вперед и назад. Для этого он использует буфер, который хранит временные данные в памяти компьютера, получать видео-файл. Несмотря на то, что данные фрагментированы, это не настоящая потоковая передача.

потокового происходит в режиме реального времени, и куски данных. Трансляция осуществляется в прямом эфире. Клиенты, слушающие трансляцию, не могут быстро перемотать или перемотать назад. В видеопотоках данные отбрасываются после воспроизведения.

потоковый сервер поддерживает двустороннее соединение со своим клиентом, в то время как веб-сервер закрывает соединение после ответа сервера.

полезно ссылки:

  1. http://www.slideshare.net/auroraeosrose/writing-and-using-php-streams-and-sockets-zendcon-2011 обеспечивает очень ясное

еще один момент (для чтения положение файла):

  1. stream может позволить вам сделать что-то еще перед finished reading all content of the file.
  2. вы можете сохранить память, потому что не нужно загружать все содержимое файла за один раз.

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

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

суть потока в том, что мы ограничиваем наше внимание тем, что важно. Имея стандартный абстракция, мы можем выполнять общие операции. Даже если вы не хотите, например, искать файл или HTTP-ответ для URL-адресов сегодня, это не значит, что вы не захотите завтра.

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

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

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

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

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

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

Я буду держать его коротким, Я просто пропустил слово здесь:

потоки очереди обычно хранится в буфере, содержащем любые данные.

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