Java套接字监听器CPU负载100%

时间:2017-10-18 10:41:51

标签: java sockets load

我需要不断地听远程套接字并对给定的输入作出反应。

public void listen(String ip, int port) {
    try (
      Socket socketListener = new Socket(ip, port);
      BufferedReader portReader = new BufferedReader(new InputStreamReader(socketListener.getInputStream()));
    ) {
      while (true) {
        while (!portReader.ready()) {
          // Wait for next PORT message
        }

        Logger.log(LogComponent.SOCKET, "Event received");
      }
    }
  }

上面的代码使用100%的CPU负载,我做错了什么?

调试时我可以看到while-!portreader-loop是恶人。但我发现的大多数例子都是以同样的方式做到的。

编辑#1

考虑到您的意见我现在有以下解决方案:

try {

  Socket SocketListener = new Socket(ip, port);
  BufferedReader portReader =
    new BufferedReader(
      new InputStreamReader(SocketListener.getInputStream())
    );

  // We do not use common while(true)-pattern for reading the input.
  // Instead, we check for new input 3 times a second.
  ScheduledExecutorService executor = Executors.newScheduledThreadPool(10);
  executor.scheduleAtFixedRate(() -> {
    try {
      processInput(portReader);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }, 0, 333, TimeUnit.MILLISECONDS);

} catch (Exception exception) {
  exception.printStackTrace();
}

processInput(0)现在正在采取行动。 与使用简单的Thread.sleep()相比,这样可以获得更好的性能结果 - 尽管我不明白为什么。

使用这种方法时:代码是否会丢失来自套接字的一些消息?我的意思是在间隔期间?

2 个答案:

答案 0 :(得分:0)

问题是你的内部代码(true)正在占用所有CPU。进行一次改变,如:

public void listen(String ip, int port) {
    try (Socket socketListener = new Socket(ip, port);
    BufferedReader portReader = new BufferedReader(new InputStreamReader(socketListener.getInputStream()));) {
        while (true) {
            while (!portReader.ready()) {
              // Wait for next PORT message
                try {
                    Thread.sleep(1);
                } catch(InterruptedException e) {
                    //handle InterruptedException
                }
            }
            Logger.log(LogComponent.SOCKET, "Event received");
        }
    }
} 

答案 1 :(得分:0)

您的CPU正忙,因为它是while循环中的处理指令。

为避免这种情况,您应该使用等待连接套接字的函数。如果您正在等待传入连接,请使用Socket.accept()。这将阻止线程(即线程不会被调度执行),直到建立连接。

请勿像其他人所建议的那样使用Thread.sleep()。虽然这确实在一定程度上降低了CPU使用率,但它仍然会不必要地烧掉CPU,并且会引入延迟。这是一个糟糕的工程实践。

除此之外,您可能希望研究非阻塞或异步I / O. See here了解更多信息。