Предисловие:
Недавно при анализе RPC Hadoop (протокол вызова удаленной процедуры), протокол, который запрашивает услуги у удаленных компьютерных программ через сеть без понимания базовой сетевой технологии. Вы можете обратиться к механизму: http://baike.baidu.com/view/32726.htm), было обнаружено, что внедрение механизма RPC Hadoop в основном использует две технологии: Dynamic Proxy (вы можете ссылаться на блог: http://wixiaolu.iteye.com/blog/14777744) и java. Чтобы правильно проанализировать исходный код RPC Hadoop, я думаю, что необходимо сначала изучить принципы и конкретную реализацию Java Nio.
В этом блоге я в основном анализирую Java Nio с двух направлений
Оглавление:
один. Разница между Java Nio и блокировкой ввода -вывода
1. Блокировка модели связи ввода/вывода
2. Java Nio Principle and Communication Model 2. Java Nio Server и Client Code реализация
Конкретный анализ:
один. Разница между Java Nio и блокировкой ввода -вывода
1. Блокировка модели связи ввода/вывода
Если у вас есть определенное понимание блокировки ввода -вывода, мы знаем, что блокировка ввода -вывода блокируется при вызове метода inputstream.read (), он подождает, пока данные не придут (или тайм -ауты) перед возвращением; Аналогичным образом, при вызове метода Serversockeocke.accept () он будет блокировать, пока не будет клиентское соединение перед возвращением. После того, как каждый клиент подключается, сервер запустит поток для обработки запроса клиента. Схема модели связи блокировки ввода/вывода выглядит следующим образом:
Если вы тщательно проанализируете это, вы обязательно обнаружите, что есть некоторые недостатки блокировки ввода -вывода. Основываясь на блокирующей модели связи ввода -вывода, я суммировал ее два недостатка:
1. Когда есть много клиентов, будет создано большое количество обработчиков. И каждый поток занимает место в стеке и некоторое время процессора
2. Блокировка может привести к частым переключению контекста, и большая часть контекста может быть бессмысленным.
В этом случае не блокирующий ввод-вывод имеет свои перспективы применения.
2. Java Nio Principle и модель коммуникации
Java Nio была запущена в JDK1.4, и можно сказать, что это как «новый ввод-вывод», либо не блокирующий ввод-вывод. Вот как работает Java Nio:
1. Выделенная нить обрабатывает все события IO и отвечает за распространение.
2. Механизм, управляемый событиями: запускает, когда прибывает событие, а не мониторинг событий одновременно.
3. Связь потока: потоки общаются через ожидание, уведомление и другие средства. Убедитесь, что каждый контекст имеет смысл. Уменьшите ненужный переключение потока.
Прочитав некоторую информацию, я опубликовал рабочую схему Java Nio, которую я понимаю:
(Примечание: поток обработки каждого потока, вероятно, читает данные, декодирование, вычислительную обработку, кодирование и отправку ответов.)
Сервер Java Nio должен только запустить специальную ветку для обработки всех событий IO. Как реализована эта модель коммуникации? Ха -ха, давайте вместе рассмотрим его загадку. Java Nio использует двусторонний канал для передачи данных, а не односторонний поток, и на канале могут быть зарегистрированы интересующие события. Всего есть четыре события:
| Название события | Соответствующее значение |
| Сервер получает события подключения клиента | Selectionkey.op_accte (16) |
| Событие сервера клиентского соединения | Selectionkey.op_connect (8) |
| Читать события | SelectionKey.op_read (1) |
| Написать события | SelectionKey.op_write (4) |
Сервер и клиент каждый поддерживает объект, который управляет каналом, который мы называем селектором, который может обнаружить события на одном или нескольких каналах. Давайте возьмем сервер в качестве примера. Если событие чтения зарегистрировано на выборе сервера, клиент в какой -то момент отправляет некоторые данные на сервер. При блокировании ввода -вывода он вызовет метод READ () для блокировки данных, а сервер NIO добавит событие чтения в селектор. Поток обработки сервера проведет опрос для доступа к селектору. Если обнаружено, что интересное событие приходит при доступе к селектору, оно будет обрабатывать эти события. Если не появится никакого интереса, то поток обработки будет блокироваться, пока не появится интересное событие. Ниже приведена схематическая схема модели связи Java Nio, которую я понимаю:
два. Java Nio Server и Client Code реализация
Чтобы лучше понять Java Nio, ниже приводится простая реализация кода для сервера и клиента.
Сервер:
Пакет Cn.nio; импортировать java.io.ioexception; Импорт java.net.inetsocketAddress; Импорт java.nio.bytebuffer; Импорт java.nio.channels.selectionKey; импортировать java.nio.channels.selector; импортировать java.nio.channels.serversocketchannel; импортировать java.nio.channels.socketchannel; импортировать java.util.iterator; /*** Nio Server* @author Small Path*/public Class nioServer {// Channel Manager Private Selecter; / ** * Получите канал Serversocke и выполните некоторую работу по инициализации на канале * @param, связанный с портом, * @throhs ioexception */ public void initserver (int port) бросает ioexception {// Получить сервер Serversockecocte Channel Serversocketchannel ServerChannel = serversocketchannel.open (); // Установить канал в не блокирующий ServerChannel.configureBlocking (false); // Связано Serversocket, соответствующий этому каналу с портом ServerChannel.socket (). Bind (New InetsocketAddress (Port)); // Получить менеджер канала this.selector = selector.open (); // Свяжите менеджер канала с каналом и зарегистрируйте событие SelectionKey.op_accept для канала. После регистрации события // Когда событие прибудет, Selector.select () вернется. Если событие не достигнет selector.select () будет блокировать. ServerChannel.register (SELECTER, SELECTIONKEY.OP_ACECTE); } /*** Используйте опрос, чтобы прослушать, есть ли события на селекторе, которые необходимо обработать. Если это так, это будет обработано * @Throws ioException */ @suppresswarnings ("uncecked") public void listen () бросает ioexception {System.out.println ("Серверный запуск успешно!"); // Опрос для доступа к селектору, в то время как (true) {// Когда наступает зарегистрированное событие, метод возвращается; В противном случае метод будет продолжать блокировать селектор. Select (); // Получить итератор выбранного элемента в селекторе, а выбранный элемент является зарегистрированным элементом итератора события = this.selector.selectedKeys (). Iterator (); while (ite.hasnext ()) {selectionKey key = (selectionKey) ite.next (); // Удалить выбранную ключ, чтобы предотвратить повторную обработку item.remove (); // Клиент запрашивает событие подключения if (key.isaceceptable ()) {servercocketchannel server = (serversocketchannel) .Channel (); // Получить канал для подключения к клиентскому Socketchannel Channel = server.accept (); // установить на не блокирующий канал. ConfigureBlocking (false); // Вы можете отправить информацию клиенту здесь Channel.write (bytebuffer.wrap (new String («Отправить сообщение клиенту»). GetBytes ())); // После того, как соединение с клиентом будет успешным, чтобы получить информацию клиента, вам необходимо установить разрешения на чтение для канала. channel.register (this.selector, selectionkey.op_read); // было получено читаемое событие} else if (key.isReadable ()) {read (key); }}}} / ** * События обработки, которые считывают сообщения, отправленные клиентом * @param key * @throws ioexception * / public void Read (KeyKey Key) бросает ioException {// Сервер может читать сообщения: получить канал сокета, где происходит событие. Socketchannel Channel = (socketchannel) key.channel (); // Создать буфер считывания буфера Bytebuffer Buffer = bytebuffer.allocate (10); Channel.read (Buffer); byte [] data = buffer.array (); String msg = new String (data) .trim (); System.out.println («Сервер получил сообщение:»+msg); Bytebuffer Outbuffer = bytebuffer.wrap (msg.getbytes ()); channel.write (Outbuffer); // Отправить сообщение обратно клиенту}/ *** Test Test* @throhs ioexception*/ public static void main (string [] args) Throws ioException {noserver server = new noserver (); Server.initserver (8000); server.listen (); }} Клиент:
Пакет Cn.nio; импортировать java.io.ioexception; Импорт java.net.inetsocketAddress; Импорт java.nio.bytebuffer; Импорт java.nio.channels.selectionKey; импортировать java.nio.channels.selector; импортировать java.nio.channels.socketchannel; импортировать java.util.iterator; /*** nio client* @author small path*/public class nioclient {// Channel Manager Private Selecter; / ** * Получите канал сокета и сделайте некоторую инициализацию канала * @param ip. IP -адрес сервера, подключенного к * @param, номер порта сервера, подключенного к * @Throws ioException */ public void initClient (String ip, int port) throws ioException {// Quep a Get socket Channel Socketchannel Channel = socketchannel.open (); // Установить канал в не блокирующий канал. ConfigureBlocking (false); // Получить менеджер канала this.selector = selector.open (); // Клиент подключается к серверу. Фактически, выполнение метода не реализует соединение. Вам нужно позвонить // использовать channel.finishConnect (); в методе прослушивания () для завершения канала соединения. Concect (New InetSocketAddress (IP, Port)); // Связайте менеджер канала с каналом и зарегистрируйте событие SelectionKey.op_connect для канала. channel.register (selector, selectionkey.op_connect); } /*** Используйте опрос, чтобы прослушать, есть ли события на селекторе, которые необходимо обработать. Если это так, это будет обработано * @Throws ioException */ @suppresswarnings ("unchecked") public void listen () бросает ioexception {// опрос для доступа к селектору, while (true) {selector.select (); // Получить итератор для выбранного элемента в элементе итератора селектора = this.selector.selectedKeys (). Iterator (); while (ite.hasnext ()) {selectionKey key = (selectionKey) item.next (); // Удалить выбранную ключ, чтобы предотвратить повторную обработку item.remove (); // Событие подключения происходит if (key.isconnectable ()) {socketchannel Channel = (socketchannel) .Channel (); // Если подключение подключено, заполните соединение if (channel.isconnectionpending ()) {channel.finishConnect (); } // Установить на не блокирующий channel.configureblocking (false); // Вы можете отправить информацию на серверный канал. // После успешного соединения с сервером, чтобы получить информацию о сервере, канал должен быть установлен для чтения разрешений. channel.register (this.selector, selectionkey.op_read); // было получено читаемое событие} else if (key.isReadable ()) {read (key); }}}} /*** События обработки, которые считывают сообщения, отправляемые сервером* @param key* @throws ioexception* /public void reade (key key keekey) throws ioexception {// То же, что и метод чтения сервера} /*** Начало клиент* @Throws IOExcept Nioclient (); Client.InitClient ("LocalHost", 8000); client.listen (); }}краткое содержание:
Наконец, анализ динамического прокси и Java Nio завершен. Ха -ха, следующее предназначено для анализа исходного кода механизма RPC Hadoop. Адрес блога: http://weixiaolu.iteye.com/blog/1504898. Однако, если у вас есть какие -либо возражения против вашего понимания Java Nio, вы можете обсудить это вместе.
Если вам нужно перепечатать, укажите источник: http://weixiaolu.iteye.com/blog/1479656