我需要不断地听远程套接字并对给定的输入作出反应。
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()相比,这样可以获得更好的性能结果 - 尽管我不明白为什么。
使用这种方法时:代码是否会丢失来自套接字的一些消息?我的意思是在间隔期间?
答案 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了解更多信息。