2016-12-27 7 views
-1

Код для эхо-сервера с использованием однопоточный ввода/вывода JavaЯвляется ли JAVA NIO тратой процессорных циклов непрерывным циклом?

public static void main(String[] args) throws Exception { 

    // create socket 
    int port = 4444; 
    ServerSocket serverSocket = new ServerSocket(port); 
    System.err.println("Started server on port " + port); 

    try { 

     // repeatedly wait for connections, and process 
     while (true) { 

      // a "blocking" call which waits until a connection is requested 
      Socket clientSocket = serverSocket.accept(); 
      System.err.println("Accepted connection from client"); 

      // open up IO streams 
      BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); 
      PrintStream out = new PrintStream(clientSocket.getOutputStream()); 

      // waits for data and reads it in until connection dies 
      // readLine() blocks until the server receives a new line from client 
      String s; 
      while ((s = in.readLine()) != null) { 
       out.print(s); 
      } 

      // close IO streams, then socket 
      System.err.println("Closing connection with client"); 
      out.close(); 
      in.close(); 
      clientSocket.close(); 
     } 
    } finally { 
     serverSocket.close(); 
    } 

} 

кода для того же с помощью NIO

public static void main(String[] args) throws IOException { 
    ServerSocketChannel server = ServerSocketChannel.open(); 
    server.socket().bind(new InetSocketAddress(PORT_NUMBER)); 
    server.socket().setReuseAddress(true); 
    server.configureBlocking(false); 

    Selector selector = Selector.open(); 
    server.register(selector, SelectionKey.OP_ACCEPT); 

    ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE); 
    while (true) { 
     int channelCount = selector.select(); 
     if (channelCount > 0) { 
      Set<SelectionKey> keys = selector.selectedKeys(); 
      Iterator<SelectionKey> iterator = keys.iterator(); 
      while (iterator.hasNext()) { 
       SelectionKey key = iterator.next(); 
       iterator.remove(); 

       if (key.isAcceptable()) { 
        SocketChannel client = server.accept(); 
        client.configureBlocking(false); 
        client.register(selector, SelectionKey.OP_READ, client.socket().getPort()); 
       } else if (key.isReadable()) { 
        SocketChannel client = (SocketChannel) key.channel(); 
        System.out.println("port: " + key.attachment()); 
        if (client.read(buffer) < 0) { 
         key.cancel(); 
         client.close(); 
        } else { 
         buffer.flip(); // read from the buffer 
          /* 
          * byte[] received = new byte[buffer.remaining()]; 
          * buffer.get(received); buffer.clear(); // write into the buffer 
          * buffer.put(received); buffer.flip(); // read from the buffer 
          */ 
         client.write(buffer); 
         buffer.clear(); // write into the buffer 
        } 
       } 
      } 
     } 
    } 
} 

Здесь с помощью обычного ввода/вывода основной нити приходит и ждать в гнездо .принять вызов. Но NIO этого не делает, поскольку socketChannel.accept() не является блокирующим вызовом.

Таким образом, программа NIO будет непрерывно работать в цикле? И привести к растрате циклов процессора? Могу ли я написать программу в лучшем виде. Извините, я очень новичок в JAVA NIO и асинхронном программировании.

+0

Java NIO не работает непрерывно. Возможно, ваш код, но тогда это будет ваш код, который тратит процессорные циклы, а не на Java NIO. NB Здесь нет ничего [tag: асинхронный]. – EJP

ответ

3

В нормальном IO нить заблокирована на serverSocket.accept().

С NIO нить заблокирована на selector.select().

С JavaDoc из Selector#select():

Этот метод выполняет операцию выбора блокирования.


Почему это называется "не блокирует IO"?

На самом деле, ваш первый пример (с нормальным IO) имеет два блокирующих вызова: server.accept() и in.readLine().

Теперь рассмотрим случай с плохо себя чувствующим клиентом: он открывает соединение с сервером, но никогда не отправляет никаких данных. При нормальном IO серверный поток ожидает в in.readLine() данных для поступления и не может обслуживать другого клиента до тех пор, пока первый клиент не закроет его соединение.

С NIO изображение отличается: если клиент открывает соединение, поток сервера просыпается, server.accept() s подключается и регистрирует SocketChannel с тем же селектором. Затем серверный поток снова ждет селектора через selector.select(). Теперь есть две возможности разбудить поток сервера: либо другой клиентский, либо первый клиент, отправляющий некоторые данные.

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

+0

Спасибо Томас. Не знал, что Selector # select является блокирующим вызовом. Тогда почему он называется Non Blocking IO, когда один из его API фактически блокирует -_- Извините за мое невежество. – Ajay

+1

@Ajay если добавлено более пояснительный текст. Я надеюсь, что яснее проясню вопрос о неблокирующем IO - иначе не стесняйтесь спрашивать снова –

+0

Спасибо, что объяснил это ясно Томасу. Теперь я понял это ясно. Спасибо, что потратили свое время на мой запрос. – Ajay

 Смежные вопросы

  • Нет связанных вопросов^_^