标题翻译
Java application with TCP sockets is using 100% of CPU
问题
以下是服务器代码部分的翻译:
public void listen() throws IOException
{
try (ServerSocket serverSocket = new ServerSocket(port);
Socket clientSocket = serverSocket.accept();
DataOutputStream outputStream = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));)
{
String data = null;
while ((data = bufferedReader.readLine()) != null)
{
Message message = Message.deserializeMessage(data);
synchronized (PeerNode.requestHistory)
{
if (PeerNode.requestHistory.keySet().contains(message))
{
continue;
}
}
if (message.getType() == 0 && message.getHopCount() < 1) {
continue;
}
switch (message.getType()) {
case 0:
synchronized (PeerNode.sharedRequestBuffer) {
PeerNode.sharedRequestBuffer.offer(message);
}
break;
case 1:
synchronized (PeerNode.sharedReplyBuffer) {
PeerNode.sharedReplyBuffer.offer(message);
}
break;
case 2:
synchronized (PeerNode.numberOfItems) {
if (PeerNode.numberOfItems > 0) {
PeerNode.numberOfItems -= 1;
}
outputStream.writeBytes("0" + "\n");
}
break;
}
synchronized (PeerNode.requestHistory) {
PeerNode.requestHistory.put(message, 0);
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
private ExecutorService executor = Executors.newFixedThreadPool(15);
public void listen() throws IOException
{
serverSocket = new ServerSocket(port);
while (!Thread.interrupted()) {
try {
//Server, Listening........
clientSocket = serverSocket.accept();
ServerExecutor serverExecutor = new ServerExecutor(peerID, clientSocket);
executor.submit(serverExecutor);
} catch (IOException e) {
e.printStackTrace();
}
}
serverSocket.close();
}
public class ServerExecutor implements Runnable {
private int peerID;
private Socket clientSocket;
public ServerExecutor(int _peerID, Socket _clientSocket) {
this.peerID = _peerID;
this.clientSocket = _clientSocket;
}
public void run() {
try (DataOutputStream outputStream = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));) {
String data = null;
while ((data = bufferedReader.readLine()) != null) {
Message message = Message.deserializeMessage(data);
synchronized (PeerNode.requestHistory) {
if (PeerNode.requestHistory.keySet().contains(message)) {
continue;
}
}
if (message.getType() == 0 && message.getHopCount() < 1) {
continue;
}
switch (message.getType()) {
case 0:
synchronized (PeerNode.sharedRequestBuffer) {
PeerNode.sharedRequestBuffer.offer(message);
}
break;
case 1:
synchronized (PeerNode.sharedReplyBuffer) {
PeerNode.sharedReplyBuffer.offer(message);
}
break;
case 2:
synchronized (PeerNode.numberOfItems) {
if (PeerNode.numberOfItems > 0) {
PeerNode.numberOfItems -= 1;
}
outputStream.writeBytes("0" + "\n");
}
break;
}
synchronized (PeerNode.requestHistory) {
PeerNode.requestHistory.put(message, 0);
}
}
clientSocket.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
public static Message deserializeMessage(String s)
{
Message m = new Message();
Scanner sc = new Scanner(s);
sc.useDelimiter("#");
m.setProductName(sc.next());
m.setProductId(sc.nextInt());
List<Integer> tempList = new ArrayList<>();
Scanner sct = new Scanner(sc.next());
sct.useDelimiter(",");
while (sct.hasNext()) {
tempList.add(sct.nextInt());
}
m.setMessagePath(tempList);
m.setHopCount(sc.nextInt());
m.setType(sc.nextInt());
m.setRequestId(sc.nextInt());
m.setSourcePeerId(sc.nextInt());
m.setDestinationSellerId(sc.nextInt());
m.setDestinationSellerLocation(sc.nextInt());
return m;
}
希望这些翻译能够帮助您理解代码。如果有任何疑问,请随时问我。
英文翻译
The server has to continuously listen for incoming connections and perform some logic on the data received. Every time I run the application, the CPU usage is more than 90%. Earlier I thought that the while loop might be spinning (busy waiting), but the readLine() is supposed to be a blocking call, so I don't think that is the case. Any help is appreciated!
The following is the server code:
public void listen() throws IOException
{
try( ServerSocket serverSocket = new ServerSocket(port);
Socket clientSocket = serverSocket.accept();
DataOutputStream outputStream = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));)
{
String data = null;
while((data = bufferedReader.readLine()) != null)
{
Message message = Message.deserializeMessage(data);
synchronized (PeerNode.requestHistory)
{
if(PeerNode.requestHistory.keySet().contains(message))
{
continue;
}
}
if(message.getType() == 0 && message.getHopCount() < 1) {
continue;
}
switch(message.getType()) {
case 0:
synchronized (PeerNode.sharedRequestBuffer){
PeerNode.sharedRequestBuffer.offer(message);
}
break;
case 1:
synchronized (PeerNode.sharedReplyBuffer) {
PeerNode.sharedReplyBuffer.offer(message);
}
break;
case 2:
synchronized (PeerNode.numberOfItems) {
if(PeerNode.numberOfItems > 0) {
PeerNode.numberOfItems -= 1;
}
outputStream.writeBytes("0" + "\n");
}
break;
}
synchronized (PeerNode.requestHistory) {
PeerNode.requestHistory.put(message, 0);
}
}
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
Edit: Added deserialize() method
public static Message deserializeMessage(String s)
{
Message m = new Message();
String[] objArray = s.split("#");
String[] list = objArray[2].split(",");
m.setProductName(objArray[0]);
m.setProductId(Integer.parseInt(objArray[1]));
List<Integer> tempList = new ArrayList();
for(int i=0; i<list.length; i++)
{
if(list[i].length() == 0)
continue;
tempList.add(Integer.parseInt(list[i]));
}
m.setMessagePath(tempList);
m.setHopCount(Integer.parseInt(objArray[3]));
m.setType(Integer.parseInt(objArray[4]));
m.setRequestId(Integer.parseInt(objArray[5]));
m.setSourcePeerId(Integer.parseInt(objArray[6]));
m.setDestinationSellerId(Integer.parseInt(objArray[7]));
m.setDestinationSellerLocation(Integer.parseInt(objArray[8]));
return m;
}
Edit 2: Changed deserialize() to use Scanner():
public static Message deserializeMessage(String s)
{
Message m = new Message();
Scanner sc = new Scanner(s);
sc.useDelimiter("#");
m.setProductName(sc.next());
m.setProductId(Integer.parseInt(sc.next()));
List<Integer> tempList = new ArrayList();
Scanner sct = new Scanner(sc.next());
sct.useDelimiter(",");
while(sct.hasNext())
{
tempList.add(Integer.parseInt(sct.next()));
}
m.setMessagePath(tempList);
m.setHopCount(Integer.parseInt(sc.next()));
m.setType(Integer.parseInt(sc.next()));
m.setRequestId(Integer.parseInt(sc.next()));
m.setSourcePeerId(Integer.parseInt(sc.next()));
m.setDestinationSellerId(Integer.parseInt(sc.next()));
m.setDestinationSellerLocation(Integer.parseInt(sc.next()));
return m;
}
Edit: Updated Server Code:
private ExecutorService executor = Executors.newFixedThreadPool(15);
public void listen() throws IOException
{
serverSocket = new ServerSocket(port);
while (!Thread.interrupted()) {
try
{
//Server, Listening........
clientSocket = serverSocket.accept();
ServerExecutor serverExecutor = new ServerExecutor(peerID, clientSocket);
executor.submit(serverExecutor);
}
catch (IOException e)
{
e.printStackTrace();
}
}
serverSocket.close();
}
ServerExecutor class:
public ServerExecutor(int _peerID, Socket _clientSocket)
{
this.peerID = _peerID;
this.clientSocket = _clientSocket;
}
public void run()
{
try( DataOutputStream outputStream = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));)
{
String data = null;
while((data = bufferedReader.readLine()) != null)
{
Message message = Message.deserializeMessage(data);
synchronized (PeerNode.requestHistory)
{
if(PeerNode.requestHistory.keySet().contains(message))
{
continue;
}
}
if(message.getType() == 0 && message.getHopCount() < 1) {
continue;
}
switch(message.getType()) {
case 0:
synchronized (PeerNode.sharedRequestBuffer){
PeerNode.sharedRequestBuffer.offer(message);
}
break;
case 1:
synchronized (PeerNode.sharedReplyBuffer) {
PeerNode.sharedReplyBuffer.offer(message);
}
break;
case 2:
synchronized (PeerNode.numberOfItems) {
if(PeerNode.numberOfItems > 0) {
PeerNode.numberOfItems -= 1;
}
outputStream.writeBytes("0" + "\n");
}
break;
}
synchronized (PeerNode.requestHistory) {
PeerNode.requestHistory.put(message, 0);
}
}
clientSocket.close();
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
Updated deserialize():
public static Message deserializeMessage(String s)
{
Message m = new Message();
Scanner sc = new Scanner(s);
sc.useDelimiter("#");
m.setProductName(sc.next());
m.setProductId(sc.nextInt());
List<Integer> tempList = new ArrayList();
Scanner sct = new Scanner(sc.next());
sct.useDelimiter(",");
while(sct.hasNext())
{
tempList.add(sct.nextInt());
}
m.setMessagePath(tempList);
m.setHopCount(sc.nextInt());
m.setType(sc.nextInt());
m.setRequestId(sc.nextInt());
m.setSourcePeerId(sc.nextInt());
m.setDestinationSellerId(sc.nextInt());
m.setDestinationSellerLocation(sc.nextInt());
return m;
}
答案1
得分: -1
你是否为每个新客户端连接使用了不同的线程,而且这种类型的代码不会占用如此高的CPU负载。还有其他在后台运行的功能吗?
编辑:
也许你可以尝试类似这样的做法?
while (true)
{
Socket s = null;
ServerSocket serverSocket = new ServerSocket(5555);
try
{
s = ss.accept(); //ss是服务器套接字对象
DataOutputStream out = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
//为客户端创建一个新线程
Thread t = new TaskHandler(s, in, out); //TaskHandler的run方法可以包含你想要为每个连接的客户端执行的代码
t.start();
}
catch (Exception e){
s.close();
e.printStackTrace();
}
}
这是否有所帮助?
英文翻译
Are you using different thread for each new client connection and also this kinda code will never occupy such a high % of CPU load. Is there some other functionality that's running in the background as well?
Edit:
Maybe you can try something like this?
while (true)
{
Socket s = null;
ServerSocket serverSocket = new ServerSocket(5555);
try
{
s = ss.accept(); //ss is the server socket object
DataOutputStream out = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader int = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
//create a new Thread for the client
Thread t = new TaskHandler(s, in, out); //run method of Task Handler can have the code you want to execute for each connected client
t.start();
}
catch (Exception e){
s.close();
e.printStackTrace();
}
}
Does this help?
专注分享java语言的经验与见解,让所有开发者获益!
评论