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,这仍然不是你正在寻找的解决方案,实际上比以前更糟糕。另请参阅