我需要不斷地偵聽遠程套接字並對給定的輸入做出反應。Java socket偵聽器100%的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
}
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()更好的性能結果 - 雖然我不明白爲什麼。
使用此方法時:代碼是否可能會遺漏來自套接字的某些消息?我的意思是在間隔期間?
'while true'將始終以CPU允許的速度運行。因此需要一個「延遲」來減慢你的循環。計算每秒要檢查遠程套接字的頻率並插入適當的延遲。例如,等待1/10秒將導致每秒約10次檢查(減去檢查時間)。 –
您還需要提供一個標記消息結束的字節。您的代碼被設計爲讀取的方式永遠不會返回-1,您將不得不關閉流以實現此目的。 – MissingSemiColon
爲什麼你不能只執行阻塞閱讀?使用'Reader.ready()'來測試可讀性是一個錯誤的設計。如果您需要非阻塞行爲,請考慮使用SelectableChannel或Java 7中引入的異步I/O功能。 –