Почему Java nio потребляет слишком много ресурсов процессора? - PullRequest
0 голосов
/ 28 января 2020

Я разработал сервер, используя Java nio. И несколько соединений (60-70) установлено. Хотя только соединения установлены и данные не передаются, он потребляет 30% моего процессора (i7 8-го поколения. 12 ядер). В случае передачи данных это составляет 80-90%. Когда я анализирую программу с помощью jvisualvm, кажется, что используется только метод selector.select (). Интересно, что делать, чтобы уменьшить загрузку процессора.

  private void startServer() throws IOException {
        this.selector = Selector.open();
        ServerSocketChannel serverChannel = ServerSocketChannel.open();
        serverChannel.configureBlocking(false);

        // retrieve server socket and bind to port
        listenAddress = new InetSocketAddress("localhost", 8090);
        serverChannel.socket().bind(listenAddress);
        serverChannel.register(this.selector, SelectionKey.OP_ACCEPT);

        System.out.println("Server started...");

        while (true) {
            // wait for events
            this.selector.select();

            //work on selected keys
            Iterator keys = this.selector.selectedKeys().iterator();
            while (keys.hasNext()) {
                SelectionKey key = (SelectionKey) keys.next();

                // this is necessary to prevent the same key from coming up 
                // again the next time around.
                keys.remove();

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

                if (key.isAcceptable()) {
                    this.accept(key);
                }
                else if (key.isReadable()) {
                    this.read(key);
                }
                else if (key.isWritable()) {
                    this.write(key);
                }
                else if (key.isConnectable()) {
                    this.connect(key);
                }
            }
        }
    }


    private void accept(SelectionKey key) throws IOException {
        ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();
        SocketChannel channel = serverChannel.accept();
        channel.configureBlocking(false);

        // register channel with selector for further IO
        dataMapper.put(channel, new ArrayList());
        channel.register(this.selector, SelectionKey.OP_READ);
    }

    //read from the socket channel
    private void read(SelectionKey key) throws IOException {
        SocketChannel channel = (SocketChannel) key.channel();
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        int numRead = -1;
        numRead = channel.read(buffer);

        if (numRead == -1) {
            this.dataMapper.remove(channel);
            channel.close();
            key.cancel();
            return;
        }

        processBuffer(buffer);
    }

    public void startClient() throws IOException, InterruptedException {
        String remoteHost = "localhost";
        int remotePort = 8090
        SocketChannel client = SocketChannel.open();
        client.configureBlocking(false);

        client.bind(new InitSocketAddress(0);
        client.setOption(StandardSocketOptions.SO_KEEPALIVE, true);
        client.connect(new InetSocketAddress(remoteHost, remotePort));

        client.register(this.selector, SelectionKey.OP_CONNECT);
    }

   public void connect(SelectionKey key){
       SelectableChannel channel = key.channel();
       SocketChannel socketChannel = (SocketChannel) channel;

       boolean isConnected = socketChannel.finishConnect();
       if(!isConnected)
           System.out.println("Not Connectted!");

   }

   public void write(SelectionKey key){
       SocketChannel socketChannel = (SocketChannel) channel;

       ByteByffer buffer = getBuffer();

       while(buf.remaining()>0){
           socketChannel.write(buf)
       }

       //we wrote the data, now we interested in waiting for data.
       key.interestOps(SelectionKey.OP_READ);

   }

1 Ответ

0 голосов
/ 29 января 2020

Это может произойти, если ваш select () возвращает 0. Вы можете напечатать некоторый журнал, чтобы проверить это.

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

...