Чи можете ви пояснити поняття потоків?


186

Я розумію, що потік - це подання послідовності байтів. Кожен потік забезпечує засоби для читання та запису байтів у свою задану сховище. Але в чому сенс потоку? Чому саме резервний магазин не є тим, з чим ми взаємодіємо?

З будь-якої причини ця концепція просто не натискає на мене. Я прочитав купу статей, але думаю, що мені потрібна аналогія чи щось таке.

Відповіді:


234

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

Давайте трохи забудемо про підкладку магазину і почнемо думати про аналогію з водним потоком. Ви отримуєте безперервний потік даних так само, як вода безперервно тече в річці. Ви не обов'язково знаєте, звідки беруться дані, і найчастіше вам це не потрібно; будь то з файлу, сокета або будь-якого іншого джерела, це насправді не має значення. Це дуже схоже на отримання потоку води, завдяки чому вам не потрібно знати, звідки вона надходить; будь то з озера, фонтану чи будь-якого іншого джерела, це насправді не має значення.

Це означає, що коли ти починаєш думати, що ти дбаєш лише про отримання потрібних даних, незалежно від того, звідки вони надходять, абстракції, про які говорили інші, стають зрозумілішими. Ви починаєте думати, що можете обернути потоки, і ваші методи все одно будуть працювати ідеально. Наприклад, ви можете це зробити:

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());

Побачити? Поки ваш метод не хвилює, яке джерело введення, ви можете налаштувати джерело різними способами. Абстракція дозволяє вилучити вхід від логіки обробки дуже елегантно.

Зауважте, що потік, який ми створили самі, не має резервного магазину, але він все ще ідеально відповідає нашим цілям.

Отже, підсумовуючи, потік - це лише джерело введення, приховуючи (абстрагуючи) інше джерело. Поки ви не порушите абстракцію, ваш код буде дуже гнучким.


6
Абстрактне мислення (і пояснення), здається, у вас у крові;) Ваша аналогія до води (і, таким чином, метафоричні посилання) нагадала мені Омара Хайяма.
java.is.for.desktop

@HosamAly Ваше пояснення дуже чітке, але щось трохи бентежить мене в зразковому коді. Явне перетворення з рядка в Int виконується автоматично за допомогою ReadInt? я вірю, що я міг би також зробити ReadString?
Рушино

1
@Rushino У наведеному вище коді немає перетворень. Метод ReadIntвизначається в самому верху з використанням int.Parse, який отримує повернутий рядок reader.ReadLine()і аналізує його. Звичайно, ви могли б створити подібний ReadStringметод. Це досить ясно?
Хосам Алі

Добре кажучи. Потоки до мене - це найпростіші та найпотужніші загальні абстракції в цілому програмуванні. Наявність .net basic Stream.Copyполегшує життя у багатьох програмах.
Феліпе

38

Справа в тому, що вам не слід було знати, що таке магазин підкладки - це абстракція над ним. Дійсно, може бути навіть не зберігання резервної копії - ви могли читати з мережі, а дані взагалі ніколи не зберігаються.

Якщо ви можете написати код, який працює, незалежно від того, чи говорите ви з файловою системою, пам'яттю, мережею чи іншим, що підтримує ідею потоку, ваш код набагато гнучкіший.

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


Чи не різні типи зчитувачів потоків, які використовуються в прикладі @HosamAly вище, означають, що ви знаєте, що таке резервна копія? Я вважаю, що FileStream, NetworkStream тощо ... читають з цих типів джерел. Крім того, чи існують випадки, коли ви не знаєте, яким може бути резервний магазин, і який буде динамічно вибиратися під час роботи програми? Я просто особисто не стикався з цим і хотів би дізнатися більше.
користувач137717

Також, чи можуть потокові дані передаватися через якийсь процес, коли дані генеруються чи мені потрібен доступ до повного набору даних, над яким я хочу працювати, коли починаю процес?
користувач137717

@ user137717: Ні, якщо ви просто взяли StreamReader- або краще, TextReaderтоді ваш код не знає, який потік лежить в основі потоку даних. А точніше, він може використовувати BaseStreamвластивість, щоб дізнатися тип - але це може бути тип, який ваш код ніколи не бачив. Справа в тому, що вам не варто байдуже. І так, ви можете абсолютно закінчити написання коду, який іноді буде використовуватися для мережевого потоку, а іноді і для потоку файлів. Що стосується потоків, що передають дані через процес - добре, що не було б зроблено всередині процесу ... це був би постачальник потоку.
Джон Скіт

30

Суть потоку полягає в тому, щоб забезпечити шар абстракції між вами та підкладкою. Таким чином, заданий блок коду, який використовує потік, не повинен дбати, чи зберігає резервне копіювання файл диска, пам'ять тощо.


Так, це дозволяє обмінюватися типом потоку, не порушуючи код. Наприклад, ви можете прочитати файл з одного виклику, а потім наступний буфер пам'яті.
Крейг

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

11

Не про потоки - це про плавання. Якщо ви можете плавати одним потоком, то ви можете плавати будь-яким потоком, з яким стикаєтесь.


7

Щоб додати до камери ехо, потік - це абстракція, тому вам не байдуже про базовий магазин. Це має найбільш сенс, коли ви розглядаєте сценарії з потоками та без них.

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

Якщо я хочу завантажити файл з Інтернету, мені потрібно відкрити сокет TCP, встановити з'єднання та отримати байти, поки не буде більше байтів. Мені потрібно керувати буфером, знати розмір очікуваного файлу та писати код, щоб виявити, коли з'єднання перестане, і обробляти це відповідним чином.

Скажімо, у мене є якийсь об’єкт TcpDataStream. Я створюю її з відповідною інформацією про з'єднання, потім читаю байти з потоку, поки вона не каже, що більше немає байтів. Потік обробляє управління буфером, умови закінчення даних та управління з'єднаннями.

Таким чином, потоки полегшують введення / виведення. Ви, звичайно, можете написати клас TcpFileDownloader, який робить те, що робить потік, але тоді у вас є клас, характерний для TCP. Більшість інтерфейсів потоку просто забезпечують метод Read () і Write (), а будь-які більш складні концепції обробляються внутрішньою реалізацією. Через це ви можете використовувати один і той же базовий код для читання або запису в пам'ять, дискові файли, сокети та багато інших сховищ даних.


5

Візуалізація, яку я використовую, - це конвеєрні стрічки, але не на реальних фабриках, тому що я нічого про це не знаю, але на мультиплікаційних фабриках, де предмети рухаються по лініях, отримують штампи та коробки, і підраховують і перевіряють послідовністю німих пристроїв.

У вас є прості компоненти, які роблять одне, наприклад, пристрій покласти вишню на торт. Цей пристрій має вхідний потік без вишневих тортів і вихідний потік тортів з вишнями. Є три переваги, які варто згадати, як структурувати обробку таким чином.

По-перше, це спрощує самі компоненти: якщо ви хочете покласти шоколадну глазур на торт, вам не потрібен складний пристрій, який знає все про торти, ви можете створити німий пристрій, який наклеїть шоколадну глазур на все, що подається в неї (в мультфільми, це стосується того, що не знаючи, що наступний пункт - це не торт, це Wile E. Coyote).

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

По-третє, пристроям не потрібно керувати товарами, боксами або розпаковуванням. Найефективніший спосіб агрегування та упаковки речей мінливий: можливо, сьогодні ви складаєте свої торти в коробки з 48 і відправляєте їх вантажівкою, але завтра ви хочете відправити коробки з шести у відповідь на замовлення. Цей вид змін може бути здійснений шляхом заміни або перенастроювання машин на початку та в кінці виробничої лінії; вишневу машину в середині рядка не потрібно змінювати, щоб обробляти різну кількість елементів за один раз, вона завжди працює з одним елементом за один раз, і не потрібно знати, яким чином є його введення чи вихід групуючись.


Чудовий приклад аналогії як пояснення.
Річі Томас

5

Коли я вперше почув про трансляцію, це було в контексті прямої трансляції за допомогою веб-камери. Отже, один хост транслює відеовміст, а інший приймає відеовміст. Так це потокове? Ну ... так ... але прямий ефір - це конкретна концепція, і я думаю, що питання стосується абстрактної концепції Streaming. Дивіться https://en.wikipedia.org/wiki/Live_streaming

Тож перейдемо далі.


Відео - не єдиний ресурс, який можна передавати. Звук також може бути потоковим. Тож ми зараз говоримо про потокові ЗМІ. Дивіться https://en.wikipedia.org/wiki/Streaming_media . Аудіо може доставлятися від джерела до націлювання різними способами. Тому давайте порівняємо деякі методи передачі даних один одному.

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

Прогресивне завантаження Прогресивні блоки завантаження завантажують дані з потокового медіа-файлу у тимчасовий буфер. Дані в цьому буфері є працездатними: дані аудіо-відео в буфері відтворюються. Через це користувачі можуть переглядати / слухати потоковий медіа-файл під час завантаження. Можлива швидка перемотка вперед та назад, за допомогою буфера. У будь-якому випадку, прогресивне завантаження - це не пряма трансляція.

Потокове трапляється в режимі реального часу та збирає дані. Потокове реалізація реалізується в прямому ефірі. Клієнти, які слухають трансляцію, не можуть перемотати назад або назад. У відеопотоках дані відкидаються після відтворення.

Потоковий сервер підтримує двосторонній зв'язок зі своїм клієнтом, тоді як веб-сервер закриває з'єднання після відповіді сервера.


Аудіо та відео - це не єдине, що можна передавати в ефір. Давайте подивимось на поняття потоків у посібнику PHP.

Потік - це ресурсний об'єкт, який демонструє поточну поведінку. Тобто він може читатися з або записуватися лінійним способом, а також може переглядати () до довільного місця в потоці. Посилання: https://www.php.net/manual/en/intro.stream.php

У PHP ресурс - це посилання на зовнішнє джерело, наприклад, на з'єднання з базою даних. Отже, іншими словами, потік - це джерело, з якого можна прочитати або записати. Отже, якщо ви працювали fopen(), то ви вже працювали з потоками.

Приклад текстового файлу, який піддається потоковому потоку:

// Let's say that cheese.txt is a file that contains this content: 
// I like cheese, a lot! My favorite cheese brand is Leerdammer.
$fp = fopen('cheese.txt', 'r');

$str8 = fread($fp, 8); // read first 8 characters from stream. 

fseek($fp, 21); // set position indicator from stream at the 21th position (0 = first position)
$str30 = fread($fp, 30); // read 30 characters from stream

echo $str8; // Output: I like c 
echo $str30; // Output: My favorite cheese brand is L

Zip файли можуть також передаватися в потоці. Крім цього, потокове обмеження не обмежується файлами. З'єднання HTTP, FTP, SSH та вхід / вихід можуть також передаватися в потоковому режимі.


Що говорить wikipedia про концепцію Streaming?

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

Дивіться: https://en.wikipedia.org/wiki/Stream_%28computing%29 .

Вікіпедія посилається на це: https://srfi.schemers.org/srfi-41/srfi-41.html, і письменники мають це сказати про потоки:

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

Отже, Потік - це фактично структура даних.


Мій висновок: потік - це джерело, яке може містити дані, які можна прочитати або записати послідовно. Потік не читає одразу все, що містить джерело, він читає / записує послідовно.


Корисні посилання:

  1. http://www.slideshare.net/auroraeosrose/writing-and-using-php-streams-and-sockets-zendcon-2011 Забезпечує чітку презентацію
  2. https://www.sk89q.com/2010/04/introduction-to-php-streams/
  3. http://www.netlingo.com/word/stream-or-streaming.php
  4. http://www.brainbell.com/tutorials/php/Using_PHP_Streams.htm
  5. http://www.sitepoint.com/php-streaming-output-buffering-explained/
  6. http://php.net/manual/en/wrappers.php
  7. http://www.digidata-lb.com/streaming/Streaming_Proposed.pdf
  8. http://www.webopedia.com/TERM/S/streaming.html
  9. https://en.wikipedia.org/wiki/Stream_%28computing%29
  10. https://srfi.schemers.org/srfi-41/srfi-41.html

4

Це просто концепція, ще один рівень абстракції, який полегшує ваше життя. І всі вони мають спільний інтерфейс, а це означає, що ви можете їх поєднувати так, як у трубі. Наприклад, кодуйте до base64, потім zip, а потім запишіть це на диск і все в один рядок!


Це, звичайно, корисно, але я б не сказав, що це "вся суть". Навіть без прив’язки корисно мати спільну абстракцію.
Джон Скіт

Так, ти маєш рацію. Я змінив слова, щоб зробити це зрозумілим.
vava

Так, краще. Сподіваюся, ви не думали, що я занадто вибагливий!
Джон Скіт

3

Найкраще пояснення потоків, які я бачив, - це глава 3 SICP . (Можливо, вам потрібно буде прочитати перші 2 глави, щоб мати сенс, але все одно. :-)

Вони взагалі не використовують стерами для байтів, а цілі числа. Основні моменти, які я отримав від цього, були:

  • Потоки - це списки із запізненням
  • Обчислювальні витрати (прагнення обчислити все достроково, в деяких випадках) викликає великі виклики
  • Ми можемо використовувати потоки для зображення безперервно довгих послідовностей

Я фактично зараз перебуваю на главі 1 SICP. Дякую!
Роб Соберс

2
можна було б розповісти про потік SICP від інших. Важлива особливість SICP потоку є лінь , в той час як загальний потік концепція підкреслює абстракції на послідовностях даних .
象 嘉 道

2

Ще один момент (для читання ситуації з файлами):

  1. streamможе дозволити вам робити щось інше раніше finished reading all content of the file.
  2. Ви можете зберегти пам'ять, оскільки не потрібно завантажувати весь вміст файлу одразу.

1

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


1

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

Суть потоку в тому, що ми обмежуємо свою увагу тим, що важливо. Маючи стандартну абстракцію, ми можемо виконувати загальні операції. Навіть якщо ви сьогодні не хочете, наприклад, шукати файл або відповідь HTTP за URL-адресами, це не означає, що ви не хочете завтра.

Потоки спочатку були задумані, коли пам'ять була крихітною порівняно зі сховищем. Просто читання файлу C може бути значним навантаженням. Мінімізація сліду пам’яті була надзвичайно важливою. Отже, абстракція, в якій потрібно дуже мало завантажуватись, була дуже корисною. Сьогодні це не менш корисно при здійсненні мережевого спілкування і, виявляється, рідко таке обмежувальне, коли ми маємо справу з файлами. Можливість прозорого додавання таких речей, як буферизація загалом, робить його ще кориснішим.


0

Потік - це абстрагування послідовності байтів. Ідея полягає в тому, що вам не потрібно знати, звідки беруться байти, лише щоб ви могли їх читати стандартизовано.

Наприклад, якщо ви обробляєте дані через потік, то це не має значення для вашого коду, якщо дані надходять із файлу, мережевого з'єднання, рядка, крапки в базі даних тощо тощо тощо.

Немає нічого поганого у взаємодії із самим резервним магазином, за винятком того, що він прив’язує вас до реалізації резервного магазину.


0

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

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


0

Я коротко кажу, тут я просто пропустив слово:

Потоки - це черги, які зазвичай зберігаються в буфері, що містить будь-який тип даних.

(Тепер, оскільки ми всі знаємо, що таке черги, пояснювати це більше не потрібно.)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.