Вопрос о потоках в Java

#java #io

#java #io

Вопрос:

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

Но я этого не понимаю. Например, когда я говорю getOutputStream или getInputStream в сокете, я получаю InputStream который я могу связать с тем, что мне нравится. Но разве InputStream / OutputStream не абстрактные классы? Я не знаю точно, как это правильно объяснить, но я не понимаю, что соединение с сокетом, просто вызывая этот метод, автоматически создает поток / канал, по которому могут проходить байты / символы? Что на самом деле является InputStream / OutputStream? Являются ли потоки способом абстрагирования реальных источников?

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

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

Спасибо за ваше время.

Ответ №1:

InputStream / OutputStream это, ну, абстракции. Они предоставляют вам некоторый базовый API для чтения / записи байтов или групп байтов, не раскрывая фактическую реализацию. Давайте возьмем OutputStream в качестве примера:

OutputStream получает кучу байтов через общедоступный API. На самом деле вы не знаете (и не заботитесь), что происходит с этими байтами впоследствии: они отправляются. Реальная реализация может: добавлять их в файл, игнорировать их ( NullOutputStream в Apache Commons), сохранять их в памяти или… отправка через сокет.

Вот что происходит при вызове Socket.getOutputStream() : вы получаете некоторую реализацию OutputStream , просто вам все равно, это зависит от реализации и специфично. Когда вы отправляете байты в этот поток, базовая реализация будет передавать их с использованием TCP / IP или UDP. Фактически TCP / IP сам по себе является потоковым протоколом, хотя он работает с пакетами / фреймами.

Аналогичная ситуация для InputStream — вы получаете некоторую реализацию из сокета. Когда вы запрашиваете у потока несколько байтов, базовая InputStream реализация запросит у сокета OS такое же количество байтов, возможно, блокируя. Но в этом и заключается настоящее удовольствие от наследования: вам все равно! Просто используйте эти потоки любым удобным для вас способом, объединяя в цепочки, буферизуя и т.д.

Комментарии:

1. Отлично, спасибо. Это было то, что я искал, на самом деле, где я должен остановиться относительно того, что происходит.

Ответ №2:

При вызове getInputStream сокет возвращает экземпляр некоторого конкретного подкласса InputStream . Обычно вы не беспокоитесь о точном классе возвращаемого объекта; поскольку это InputStream , вы просто работаете с ним таким образом. (Подкласс может даже быть частным вложенным классом класса socket.)

Ответ №3:

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

В случае Socket реализация является SocketInputStream , которая расширяет FileInputStream

Ответ №4:

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

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

Для любого типа ввода-вывода сокетов, хотя, сказав все это о потоках, Java socket API довольно старый, и есть несколько действительно хороших доступных альтернатив, которые его дополняют и проще в использовании. Я настоятельно рекомендую Netty, используя который, вы можете забыть о потоках и сосредоточиться на POJOs и на том, как их кодировать и декодировать.