2015-09-08 1 views
0

здесь важный код:Как улучшить производительность следующего кода с помощью socketchannel? И как я могу получить строку UTF8?

public void setSelector() { 
    try { 

     this.writebuf.clear(); 
     this.selector = Selector.open(); 
     int interestSet = SelectionKey.OP_READ | SelectionKey.OP_WRITE; 
     SelectionKey selectionKey = this.socketChannel.register(selector, interestSet); 


     // Checking if the buffer is in write mode 
     if (!(this.writebuf.limit() == this.writebuf.capacity())) { 
      writebuf.flip(); 
     } 

     int bytesRead = 0; 

     while (selector.select() > -1) { 

      // Wait for an event one of the registered channels 

      // Iterate over the set of keys for which events are available 
      Iterator selectedKeys = selector.selectedKeys().iterator(); 
      while (selectedKeys.hasNext()) { 
       SelectionKey key = (SelectionKey) selectedKeys.next(); 
       selectedKeys.remove(); 
       if (!key.isValid()) { 
        continue; 
       } 
       if (key.isReadable()) { 

        bytesRead = this.socketChannel.read(this.writebuf); 

        if (bytesRead > 0 && writebuf.hasRemaining()) { 
         this.writebuf.flip(); 
         this.parseSubtitleMessage(new String(writebuf.array(), charset)); 
         this.writebuf.clear(); 
         this.writebuf.flip(); 
        } 
       } 
       if (key.isWritable()) { 
       // Not yet implemented 
       } 
      } 
     } 

    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 

Socketchannel установлен в режим nonblocking. Первой проблемой является то, что цикл while создает огромную рабочую нагрузку. В основном мне нужно что-то, что pause код до READ или WRITEevent происходит. Еще одна проблемная часть этого кода:

this.parseSubtitleMessage(new String(writebuf.array(), charset));

Я знаю, что, когда я вызываю метод array() я получу весь буфер, включая некоторые forgotten байт из предыдущего сообщения, даже если я называю clear метод. Я нашел решение, которое использует цикл while для итерации по одиночным байтам, пока значение buffer.hasRemaining() не будет установлено в false. Но я не знаю, как использовать указанную кодировку в этом случае.

Edit: я решил свою "бесконечный цикл" проблема, вот фиксированный код:

public void runSelector() { 
    try { 

     this.writebuf.clear(); 

     // Checking if the buffer is in write mode 
     if (!(this.writebuf.limit() == this.writebuf.capacity())) { 
      writebuf.flip(); 
     } 

     this.selector = Selector.open(); 

     int interestSet_RW = SelectionKey.OP_READ | SelectionKey.OP_WRITE; 

     int bytesRead = 0; 

     SelectionKey selectionKey = this.socketChannel.register(selector, SelectionKey.OP_READ); 

     while(true) { 

      int readyChannels = selector.select(); 

      if(readyChannels == 0) continue; 


      Set<SelectionKey> selectedKeys = selector.selectedKeys(); 

      Iterator<SelectionKey> keyIterator = selectedKeys.iterator(); 

      while(keyIterator.hasNext()) { 

       SelectionKey key = keyIterator.next(); 

       if (!key.isValid()) { 
        continue; 
       } 

       // Check if there's something to write in the queue and change interestops apropriately. 
       if (monitorObject.tosendIsEmpty()) { 
        selectionKey.interestOps(SelectionKey.OP_READ); 
       } else { 
        selectionKey.interestOps(interestSet_RW); 
       } 

       if (key.isWritable()) { 
       } 

       if (key.isReadable()) { 
        bytesRead = this.socketChannel.read(this.writebuf); 

        if (bytesRead > 0 && writebuf.hasRemaining()) { 
         this.parseSubtitleMessage(new String(this.writebuf.array(), charset)); 
         this.writebuf.clear(); 
        } 
       } 
       keyIterator.remove(); 
      } 
     } 




    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 

я непреднамеренно создал sligthly дублировать нить. Мои навыки Google, вероятно, были действительно плохими в тот день. Однако вторая проблема остается, и я определенно буду признателен вам за вашу помощь. Спасибо

Редактировать 2: Так что я исправил и вторую проблему. Вот код:

   if (key.isReadable()) { 

        bytesRead = this.socketChannel.read(this.writebuf); 

        bytes = new byte[bytesRead]; 

        int x = 0; 

        this.writebuf.flip(); 

        while(this.writebuf.hasRemaining()) { 
         bytes[x] = this.writebuf.get(); 
         x++; 
        } 

        System.out.println(new String(bytes, charset)); 

        this.writebuf.flip(); 
        this.writebuf.clear(); 
       } 
+0

не связана с реальной проблемой, но вы можете начать с фиксацией * непроверенные * предупреждения, что ваш код генерирует (например, 'selectedKeys() 'возвращает общий набор). Это также снимает необходимость приведения. – dhke

+0

Вам действительно нужно использовать NIO? Вы можете взглянуть на Netty (http://netty.io/), что делает его намного проще. –

+0

Мне не нужно использовать NIO. Я просто новичок в Java, и я не знал о netty. Я запомню это в следующий раз. благодаря – Jan

ответ

0

Вот окончательное решение:

public void runSelector() { 
    try { 

     this.writebuf.clear(); 

     // Checking if the buffer is in write mode 
     if (!(this.writebuf.limit() == this.writebuf.capacity())) { 
      writebuf.flip(); 
     } 

     this.selector = Selector.open(); 

     int interestSet_RW = SelectionKey.OP_READ | SelectionKey.OP_WRITE; 

     int bytesRead = 0; 

     byte[] bytes = null; 

     SelectionKey selectionKey = this.socketChannel.register(selector, SelectionKey.OP_READ); 

     while(true) { 

      int readyChannels = selector.select(); 

      if(readyChannels == 0) continue; 


      Set<SelectionKey> selectedKeys = selector.selectedKeys(); 

      Iterator<SelectionKey> keyIterator = selectedKeys.iterator(); 

      while(keyIterator.hasNext()) { 

       SelectionKey key = keyIterator.next(); 

       if (!key.isValid()) { 
        continue; 
       } 

       // Check if there's something to write in the queue and change interestops apropriately. 
       if (monitorObject.tosendIsEmpty()) { 
        selectionKey.interestOps(SelectionKey.OP_READ); 
       } else { 
        selectionKey.interestOps(interestSet_RW); 
       } 

       if (key.isWritable()) { 
       } 

       if (key.isReadable()) { 

        bytesRead = this.socketChannel.read(this.writebuf); 

        bytes = new byte[bytesRead]; 

        int x = 0; 

        this.writebuf.flip(); 

        while(this.writebuf.hasRemaining()) { 
         bytes[x] = this.writebuf.get(); 
         x++; 
        } 

        System.out.println(new String(bytes, charset)); 

        this.writebuf.flip(); 
        this.writebuf.clear(); 
       } 
       keyIterator.remove(); 
      } 
     } 




    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 
Смежные вопросы