Java — Реализация обмена сообщениями из кода с консолью


Содержание

10. Урок по Java. Сетевое программирование

В этом уроке мы посмотрим три примера из сетевого программирования в Java

Создадим первый проект, в нем класс Example

Наша программа выведет ip и имя хоста (на примере яндекса)

Это все конечно весело, давайте перейдем к реализации посложнее

В консоли Eclipse внизу вводите сообщение, на него увидите ответ.

Реализация UDP сервера и клиента на Java:

Перейдем к реализации TCP сервера и клиента:

Внизу Eclipse в консоли вводите сообщение, Вы увидите ответ.

Пример простого клиент-серверного приложения на Java

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

Основные компоненты приложения

Основными компонентами, естественно, являются непосредственно клиент и сервер. Однако, кроме них необходим еще пакет вспомогательных классов, которые, в простейшем случае, будут отвечать за обмен сообщениями между клиентом и сервером. В минимальной комплектации нужны такие классы: MessageReader/MessageWriter(считывает/записывает сообщение в поток на сокете), MessageFactory(содержит идентификаторы всех возможных сообщений), набор сообщений-запросов(Request) и набор сообщений-ответов(Response). Все они будут размещены в пакете «core», который должны иметь у себя и клиент и сервер.

Рассмотрим классовую структуру всего проекта, а потом перейдем к реализации.

Классовая структура клиент-серверного приложения

Исходный код клиента на Java

Разобраться с клиентом гораздо проще, он по сути своей не делает ничего супер сложного, просто создает сокет и подключается к сервер-сокету с помощью связки host:port. Лаунчер создает объект класса Client и запускает его работу. Исходный код привожу без импортов, ибо любая IDE вам их подключит(те, кто пишет на Java точно знают, что без IDE очень сложно). Кроме того, в конце статьи вы сможете скачать архив с этим проектом.

ClientLauncher.java

Client.java

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

Исходный код сервера на Java

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

Напомню, что в классе ClientSession описан основной алгоритм работы с клиентом, обмен сообщениями, данными и прочее. В классе Context содержится общая информация для всех клиентов сервера, например, пути для сохранения логов.

ServerLauncher.java

Server.java

Context.java

ClientSession.java

SessionsManager.java

Вспомогательные классы из пакета «core»

Помещу все вспомогательные классы под один кат, название классов в точности соответствует названиям из списка «классовая структура» выше, по нему вы можете определить пакет каждого класса.

Пара слов о сообщениях, классы Request и Response являются абстрактными и играют роль классификаторов сообщения. Благодаря этому очень удобно разграничивать «запросы» от «ответов». В этом примере я привел только одно сообщение — Handshake, которое отвечает за первое «рукопожатие» клиента и сервера. Все последующие сообщения должны быть прописаны в классе MessageFactory по примеру этих двух.

Скачать архив с шаблоном клиент-серверного приложения на Java

Заключение

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

Java — Реализация обмена сообщениями из кода с консолью

Для получения данных, введенных пользователем, а также для вывода сообщений нам необходим ряд классов, через которые мы сможем взаимодействовать с консолью. Частично их использование уже рассматривалось в предыдущих темах. Для взаимодействия с консолью нам необходим класс System . Этот класс располагается в пакете java.lang, который автоматически подключается в программу, поэтому нам не надо дополнительно импортировать данный пакет и класс.

ВЫВОД НА КОНСОЛЬ.

Для создания потока вывода в класс System определен объект out . В этом объекте определен метод println , который позволяет вывести на консоль некоторое значение с последующим переводом консоли на следующую строку:

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

Но с помощью метода System.out.print также можно осуществить перевод каретки на следующую строку. Для этого надо использовать escape-последовательность \n:

Если у нас есть два числа, и мы хотим вывести их значения на экран, то мы можем, например, написать так:

Но в Java есть также функция для форматированного вывода, унаследованная от языка С: System.out.printf() . С ее помощью мы можем переписать предыдущий пример следующим образом:

В данном случае символы %d обозначают спецификатор, вместо которого подставляет один из аргументов. Спецификаторов и соответствующих им аргументов может быть множество. В данном случае у нас только два аргумента, поэтому вместо первого %d подставляет значение переменной x, а вместо второго — значение переменной y. Сама буква d означает, что данный спецификатор будет использоваться для вывода целочисленных значений типа int .

Кроме спецификатора %d мы можем использовать еще ряд спецификаторов для других типов данных:

  • %x : для вывода шестнадцатеричных чисел
  • %f : для вывода чисел с плавающей точкой
  • %e : для вывода чисел в экспоненциальной форме, например, 1.3e+01
  • %c : для вывода одиночного символа
  • %s : для вывода строковых значений

При выводе чисел с плавающей точкой мы можем указать количество знаков после запятой, для этого используем спецификатор на %.2f , где .2 указывает, что после запятой будет два знака. В итоге мы получим следующий вывод:

КОНСОЛЬНЫЙ ВВОД

Для получения консольного ввода в классе System определен объект in . Однако непосредственно через объект System.in не очень удобно работать, поэтому, как правило, используют класс Scanner , который, в свою очередь использует System.in. Например, создадим маленькую программу, которая осуществляет ввод чисел:

Цукерберг рекомендует:  Топ-5 советов от Дмитрия Литмановича

Так как класс Scanner находится в пакете java.util, то мы вначале его импортируем. Для создания самого объекта Scanner в его конструктор передается объект System.in . После этого мы можем получать вводимые значения. Например, чтобы получить введенное число, используется метод in.nextInt(); , который возвращает введенное с клавиатуры целочисленное значение.

В данном случае в цикле вводятся все элементы массива, а с помощью другого цикла все ранее введенные элементы массива выводятся в строчку.

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

  • next() : считывает введенную строку до первого пробела
  • nextLine() : считывает всю введенную строку
  • nextInt() : считывает введенное число int
  • nextDouble() : считывает введенное число double
  • hasNext() : проверяет, было ли введено слово
  • hasNextInt() : проверяет, было ли введено число int
  • hasNextDouble() : проверяет, было ли введено double


Кроме того, класс Scanner имеет еще ряд методов nextByte/nextShort/nextFloat/nextBoolean , которые по аналогии с nextInt считывают данные определенного типа данных.

Создадим следующую программу для ввода информации о человеке:

Консольный ввод/вывод в Java

Для получения данных, введенных пользователем, а также для вывода сообщений нам необходим ряд классов, через которые мы сможем взаимодействовать с консолью. Частично их использование уже рассматривалось в предыдущих темах. Для взаимодействия с консолью нам необходим класс System . Этот класс располагается в пакете java.lang, который автоматически подключается в программу, поэтому нам не надо дополнительно импортировать данный пакет и класс.

Вывод на консоль

Для создания потока вывода в класс System определен объект out . В этом объекте определен метод println , который позволяет вывести на консоль некоторое значение с последующим переводом консоли на следующую строку:

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

Но с помощью метода System.out.print также можно осуществить перевод каретки на следующую строку. Для этого надо использовать escape-последовательность \n :

Если у нас есть два числа, и мы хотим вывести их значения на экран, то мы можем, например, написать так:

Форматирование

Но в Java есть также функция для форматированного вывода, унаследованная от языка С: System.out.printf() . С ее помощью мы можем переписать предыдущий пример следующим образом:

В данном случае символы %d обозначают спецификатор, вместо которого подставляет один из аргументов. Спецификаторов и соответствующих им аргументов может быть множество. В данном случае у нас только два аргумента, поэтому вместо первого %d подставляет значение переменной x, а вместо второго — значение переменной y. Сама буква d означает, что данный спецификатор будет использоваться для вывода целочисленных значений типа int .

Кроме спецификатора %d мы можем использовать еще ряд спецификаторов для других типов данных:

  • %x : для вывода шестнадцатеричных чисел
  • %f : для вывода чисел с плавающей точкой
  • %e : для вывода чисел в экспоненциальной форме, например, 1.3e+01
  • %c : для вывода одиночного символа
  • %s : для вывода строковых значений

При выводе чисел с плавающей точкой мы можем указать количество знаков после запятой, для этого используем спецификатор на %.2f , где .2 указывает, что после запятой будет два знака. В итоге мы получим следующий вывод:

Имя: Иван Возраст: 30 лет Рост: 1,70 метров

Консольный ввод

Для получения консольного ввода в классе System определен объект in . Однако непосредственно через объект System.in не очень удобно работать, поэтому, как правило, используют класс Scanner , который, в свою очередь использует System.in. Например, создадим маленькую программу, которая осуществляет ввод чисел:

Так как класс Scanner находится в пакете java.util, то мы вначале его импортируем. Для создания самого объекта Scanner в его конструктор передается объект System.in . После этого мы можем получать вводимые значения. Например, чтобы получить введенное число, используется метод in.nextInt(); , который возвращает введенное с клавиатуры целочисленное значение.

В данном случае в цикле вводятся все элементы массива, а с помощью другого цикла все ранее введенные элементы массива выводятся в строчку.

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

  • next() : считывает введенную строку до первого пробела
  • nextLine() : считывает всю введенную строку
  • nextInt() : считывает введенное число int
  • nextDouble() : считывает введенное число double
  • hasNext() : проверяет, было ли введено слово
  • hasNextInt() : проверяет, было ли введено число int
  • hasNextDouble() : проверяет, было ли введено double

Кроме того, класс Scanner имеет еще ряд методов nextByte/nextShort/nextFloat/nextBoolean, которые по аналогии с nextInt считывают данные определенного типа данных.

Создадим следующую программу для ввода информации о человеке:

Вывод в консоль и ввод пользователя с клавиатуры в Java

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

Слово «консоль» и слово «экран» в нашем случае синонимы, поэтому пугаться данных слов не нужно.
Собственно, консоль — это совокупность различных устройств (в том числе и устройств ввода/вывода) для взаимодействия человека и компьютера.

Чтение ввода с консоли

Ключевой момент: чтение ввода с консоли даёт возможность программе принимать ввод от пользователя

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

Java использует System.out для обращения к стандартному устройству вывода и System.in для стандартного устройства ввода. По умолчанию, устройство вывода – это дисплей монитора, а устройство ввода – это клавиатура. Для выполнения консольного вывода, вы просто используете метод println для отображения в консоль простых значений или строк. Консольный ввод не поддерживается напрямую в Java, но вы можете использовать класс Scanner для создания объекта для чтения ввода из System.in. Это делается так:

Синтаксис new Scanner(System.in) создаёт объект типа Scanner. Синтаксис Scanner input объявляет, что input является переменной, чей тип – Scanner. Вся строка Scanner input = new Scanner(System.in) создаёт объект Scanner и присваивает его ссылку переменной input. Объект может вызывать свои методы. Вызвать метод объекта означает запросить объект выполнить задачу. Вы можете вызвать метод nextDouble() для чтения значения double следующим образом:

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

Обратите внимание, что десятичным разделителем, в зависимости от локали вашей системы, может быть точка или запятая. Если у вас возникает ошибка InputMismatchException, то посмотрите чуть ниже.

Строка 10 отображает в консоли надпись «Введите радиус: ». Это называется prompt (подсказка, напоминание), поскольку он направляет пользователя к вводу данных. Если ваша программа ожидает ввода с клавиатуры, она всегда должна говорить пользователю, ввод каких данных от него ожидается.

print или println

Цукерберг рекомендует:  React jx - Как удалять элементы с выборкой по state в ReactJS

Метод print на десятой строке

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

Строка 8 создаёт объект Scanner. Инструкция на одиннадцатой строке считывает ввод с клавиатуры.

После того, как пользователь ввёл число и нажал клавишу Ввод (Enter), программа считывает число и присваивает его переменной radius.

Больше подробностей об объектах будет представлено в одной из последующих главах. На текущий момент просто примите, что это то, как получить вход с консоли.

Конкретный импорт

Класс Scanner находится в пакете java.util. Он импортируется на строке 2. Имеется два вида инструкций import: конкретный импорт и импорт с подстановочными символами. Конкретный импорт импортирует определённый единичный класс в инструкции import. Например, следующая инструкция импортирует Scanner из пакета java.util.

Импорт с подстановочным символом

Импорт с подстановочным символом импортирует все классы из пакета, используя звёздочку в качестве подстановочного символа. Например, следующая инструкция импортирует все классы из пакета java.util.

Разница в производительности между импортом одного класса или всех классов в пакете

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

Ещё одна программа, которая даёт пример чтения нескольких значений с клавиатуры. Программа считывает три числа и показывает их среднее арифметическое:

Листинг с номерами строк:

Код для импорта класса Scanner (строка 2) и создание объекта Scanner (строка 8) такие же, как и в предшествующем примере, как и во всех новых программах, которые вы будете писать, для чтения ввода с клавиатуры.

Строка 10 делает запрос пользователю ввести три числа. Числа считываются на строках 11-13. Вы можете ввести три числа разделив их пробелами, а затем нажать кнопку Enter, или нажимать клавишу Enter после каждого числа. Оба варианта показаны в примерах запуска этой программы.

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


Примечание: большинство программа в начальных главах этого сайта выполняют три шага – ввод, обработка и вывод, это также называется IPO (от английских input, process, and output). Ввод – это получение данных от пользователя; обработка – это выработка результата, используя ввод, а вывод – это отображение результатов.

Решение проблемы с ошибкой InputMismatchException

Если при попытке ввести число с плавающей точкой, например, такой строкой программы:

Вы получаете ошибку:

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

*Региональный стандарт, региональные настройки (проф. жарг. лока́ль от англ. locale, /lɔ.kal/ или /ləuˈkɑ:l/) — набор параметров, определяющий региональные настройки пользовательского интерфейса, такие как язык, страна, часовой пояс, набор символов и т. п.

Выходов из этой ситуации два:

  • использовать десятичный разделитель вашей локали (точку вместо запятой или запятую вместо точки)
  • чуть изменить программу – явно указать локаль

Для этого при создании объекта Scanner добавьте .useLocale(Locale.US). Например, объект создавался следующим образом:

После дополнения получается такая строка создания объекта:

Также в начале программы требуется сделать дополнительный импорт:

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

Обмен сообщениями Java-сокета между клиентом и сервером

У меня проблемы с многопоточным Java-сокетом, когда я сам узнаю о сокете на странице Oracle Java, после прочтения примера о сокетах TCP и UDP.

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

Но, интересно, когда клиент отправляет сообщение на сервер с многопоточным, а сервер имеет какое-то условие.

Пример: Когда клиент отправляет на сервер письмо A

Сервер получит и будет иметь такое состояние, как

В комментарии вышеприведенного фрагмента кода вы можете увидеть мой вопрос, потому что после того, как клиент отправит ввод, который является A, клиент отправит следующую букву типа B в такой структуре:

мой код сервера похож:

и мой клиентский код:

отредактированный

Хорошо, когда я упоминаю об этом

Клиент отправляет сообщения на сервер

и сервер получает сообщения от клиента и сравнивает его

GameHandle для обработки ввода

Это может быть самым простым решением вашей проблемы.

Я также нашел ошибку в вашем клиентском коде. Исправленный код выглядит следующим образом

Я выполнил программу на своем конце и успешно ее выполнил. Теперь у вас не должно быть никаких проблем.

Я думаю, что вы хотите принять решение, основанное на предыдущем состоянии. Тогда все, что вам нужно, это объектно-ориентированный конечный автомат. Если клиент вводит ‘A’ из исходного состояния, тогда сервер должен ожидать ‘B’ или ‘C’ качестве следующего ввода. Если клиент входит в ‘B’ а сервер находится в состоянии ‘A’ , сервер должен ожидать «D» или «E» в качестве следующего ввода. Если это то, что вы хотите, вы должны использовать шаблон государственного дизайна.

Каждое состояние, которое у вас есть, должно быть представлено Объектом.

Сначала вам нужно создать Interface для состояния и получить от него свои состояния.

Затем вы должны создать класс-оболочку для инкапсуляции ваших состояний. Этот класс обертки служит в качестве конечного автомата. Он должен поддерживать ссылку на «текущий» объект состояния.

Когда клиент вводит символ, он будет передан экземпляру обертки. Затем оболочка передаст его текущему объекту состояния. Тогда текущий State объект будет обрабатывать эти данные и определяет следующее состояние машины. Он создаст следующее состояние (объект) и обновит «текущую» ссылку на состояние класса-оболочки. Затем следующий клиентский ввод будет обрабатываться вновь созданным объектом State .

Как использовать это на своем сервере

Библиотека примеров приложений Java

Оглавление
Выбор файлов
Простейший редактор текста
Копирование файлов UNICODE
Сохранение объекта Java в файле
Произвольные классы и файлы
Буферизация потоков
Разбор конфигура-
ционного файла

Работа с консолью
Работа с классом PrintWriter
Разбор строк класса String
Загрузка и просмотр изображений
Потоки в оперативной памяти
Конвейерные потоки
Комбинирование двух потоков
Комбинирование нескольких потоков
Поиск слова в текстовом файле
Произвольный доступ к файлу
Информация о файле
Работа с каталогами
Просмотр содержимого каталога
Просмотр каталога с фильтром
Панель для выбора каталога
Список системных свойств
Сохранение списка системных свойств
Контрольная сумма файла
Копирование, переименование, удаление файлов
Архивы ZIP
Создание архива ZIP
Распаковка архива ZIP
Обход дерева каталогов

7.8. Работа приложения Java с консолью

Приложение показывает несложные приемы ввода с системной консоли текстовых строк и целых чисел, а также отображение текстовых строк на консоли.

Немного теории

Консольное автономное приложение Java, не создающее окон на базе класса Frame, общается с пользователем через символьную консоль (подобно старым программам DOS).

Для работы с консолью в классе java.lang.System определены так называемые стандартные потоки, предназначенные для ввода данных с клавиатуры, вывода обычных сообщений и сообщений об ошибках.

Цукерберг рекомендует:  Основы КоДизайна

Стандартный поток ввода определен следующим образом:

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

При работе с клавиатурой этот метод возвращает количество прочитанных символов.

Для вывода обычных сообщений используется стандартный поток вывода:

Для работы с этим потоком обычно используются методы print и println. Метод println в отличие от метода print после вывода текстового представления переданного ему аргумента выполняет перевод строки.

В классе PrintStream определено несколько реализаций метода print и println с параметрами различных типов. Вот список реализаций метода print:

Поток для вывода сообщений об ошибках выглядит следующим образом:

Для работы с этим потокам вы также можете использовать методы print и println.

Описание примера

Наше консольное приложение вводит в цикле строки и числа, отображая их на консоли:

Цикл завершится, если пользователь введет строку quit.


Рассмотрим исходный текст приложения.

Метод main

В главном классе мы определили статический метод main, который получает управление сразу после запуска приложения, а также методы getKbdString и getKbdInt. Метод getKbdString предназначен для ввода с консоли текстовых строк, а метод getKbdInt — для ввода с консоли целых чисел.

Введенные строки и числа сохраняются на время работы одной итерации цикла в переменных s и i, соответственно:

Получив управление, метод main первым делом выводит на консоль сообщение:

При этом он выполняет запись в стандартный поток вывода.

Далее запускается цикл:

В этом цикле мы сначала выводим приглашение для ввода текстовой строки, а затем вводим эту строку методом getKbdString, определенным в нашем приложении. Если пользователь ввел строку «quit», цикл завершает свою работу.

Если введена другая строка, метод main выводит на консоль приглашение для ввода целого числа. Число вводится методом getKbdInt.

Вся введенная информация отображается на консоли.

Метод getKbdString

Для ввода с клавиатуры текстовых строк мы определили метод getKbdString:

Внутри тела метода мы предусмотрели три переменные:

Массив байт bKbd заполняется символами, введенными с клавиатуры. В переменную iCnt записывается количество этих символов. И, наконец, в переменной szStr хранится строка, сформированная из массива bKbd.

Ввод символов с клавиатуры выполняется методом read:

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

Когда пользователь введет строку символов и нажмет клавишу , метод read возвратит управление. При этом в переменную iCnt будет записано количество введенных символов.

Пользуясь этой информацией, мы формируем из массива введенных символов текстовую строку класса String:

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

Результат возвращается оператором return:

Метод getKbdInt

Для ввода с клавиатуры целых чисел мы определили несложный метод getKbdInt:

Здесь мы просто вызываем метод getKbdString и преобразуем введенную этим методом строку сначала к типу Integer, а затем к типу int. Оператор return возвращает результат такого преобразования.

Блог только про Java

Учимся программировать на Java с нуля

Класс Exchanger, примеры реализации кода в Java

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

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

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

Класс Exchanger является обобщенным и объявляется приведенным ниже об­разом, где параметр V определяет тип обмениваемых данных.

В классе Exchanger определяется единственный метод exchange(), имеющий следующие общие формы:

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

Вторая форма метода exchange() позволяет определить время ожидания. Главная особенность мето­да exchange() состоит в том, что он не завершится успешно до тех пор, пока не будет вызван для одного и того же объекта типа Exchanger из двух отдель­ных потоков исполнения. Подобным образом метод exchange() синхронизи­рует обмен данными.

Дорогие читатели, в планах менять дизайн блога. Думаю натянуть HTML шаблон ThemeForest Findeo на WordPress, или найти подобный. Если есть какие-нибудь идеи обязательно оставьте их в комментарии.

В приведенном ниже примере программы демонстрируется применения клас­са Exchanger. В этой программе создаются два потока исполнения.

В одном пото­ке исполнения создается пустой буфер, принимающий данные из другого потока исполнения. Таким образом, первый поток исполнения обменивает пустую сим­вольную строку на полную.

Ниже показаны результаты выполнения данной программы.

В методе main() данной программы сначала создается объект класса Exchanger. Этот объект служит для синхронизации обмена символьными строка­ми между классами MakeString и UseString. Класс MakeString заполняет символьную строку данными, а класс UseString обменивает пустую символьную стро­ку на полную, отображая затем ее содержимое.

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

Ввод с клавиатуры Java языка

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

Для ввода данных с клавиатуры в Java используется метод System.in.read() — он возвращает код введенного символа. После его выполнения JVM останавливает программу и ждет пока пользователь введет символ с клавиатуры. Для того, чтобы вывести сам символ на консоль, выполняется его приведение к типу char :

Конечно же, использовать System.in в чистом виде не очень удобно, если нам необходимо ввести не один символ, а целую строку. В этом случае можно воспользоваться классом Scanner . Этот класс находится в пакете java.util , поэтому его надо импортировать:

Методы этого класса позволяют считывать строку, значение типа int или double .

Методы класса Scanner :

hasNextInt() — возвращает true если с потока ввода можно считать целое число.

nextInt() — считывает целое число с потока ввода.

hasNextDouble() — проверяет, можно ли считать с потока ввода вещественное число типа double .

nextDouble() — считывает вещественное число с потока ввода.

nextLine() — позволяет считывать целую последовательность символов, то есть строку.

hasNext() — проверяет остались ли в потоке ввода какие-то символы.

В следующем примере метод hasNextInt() проверяет, ввел ли пользователь целое число. И с помощью метода nextInt() считываем введенное число. Если пользователь ввел строку, то программа выведет на консоль «Вы ввели не целое число»:

Рассмотрим пример, в котором используется метод nextDouble() для считывания дробного числа. Если же пользователь введет строку, то программа завершится с ошибкой времени выполнения. Чтобы этого не происходило, перед вызовом метода nextDouble() , сделайте проверку с помощью метода hasNextDouble() :

Следующий пример использует метод nextLine() для считывания всей строки:

Понравилась статья? Поделиться с друзьями:
Все языки программирования для начинающих