Java套接字侦听器CPU负载为100%

Java套接字侦听器CPU负载为100%,java,sockets,load,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())); ) {

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

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循环是作恶者。但我发现的大多数例子都是这样做的

编辑#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()得到更好的性能结果-尽管我不明白为什么


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

问题是您的while(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");
        }
    }
} 

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

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

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


除此之外,您可能还需要研究非阻塞或异步I/O。以获取更多信息。

而true
将始终以CPU允许的速度运行。因此,需要一个
延迟
,以降低循环的速度。计算每秒检查远程套接字并插入适当延迟的频率。例如,等待1/10秒将导致每秒约10次检查(减去检查时间)。您还需要提供一个字节来标记消息的结束。您的代码设计读取的方式永远不会返回-1,您必须关闭流才能实现这一点。为什么不能执行阻塞读取?使用
Reader.ready()
测试可读性是错误的设计。如果需要非阻塞行为,考虑使用可选的通道,或者可能是java 7中引入的异步I/O特性。因为如果服务器发送数据,PoTeReal.Read()仅为真。当Debug时CPU消耗相同。服务器几乎立即接受套接字,这不是问题。然后插座持续保持打开状态。但它只是每隔几秒钟发送一次数据。谢谢你的链接!在这种情况下,您可以尝试
portReader.read()
,它应该阻止(释放线程),直到输入可用。至于你的编辑#1,你现在在另一个线程上浪费了CPU,这仍然不是你正在寻找的解决方案,实际上比以前更糟糕。另请参阅