Java应用程序使用TCP套接字,CPU占用率达到100%。

huangapple 未分类评论62阅读模式
标题翻译

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 &amp;&amp; message.getHopCount() &lt; 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 &gt; 0) {
                                PeerNode.numberOfItems -= 1;
                            }
                            outputStream.writeBytes(&quot;0&quot; + &quot;\n&quot;);
                        }
                        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(&quot;#&quot;);
        String[] list = objArray[2].split(&quot;,&quot;);
        m.setProductName(objArray[0]); 
        m.setProductId(Integer.parseInt(objArray[1]));
        List&lt;Integer&gt; tempList = new ArrayList();
        for(int i=0; i&lt;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(&quot;#&quot;);
        m.setProductName(sc.next());
        m.setProductId(Integer.parseInt(sc.next()));
        List&lt;Integer&gt; tempList = new ArrayList();
        Scanner sct = new Scanner(sc.next());
        sct.useDelimiter(&quot;,&quot;);
        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 &amp;&amp; message.getHopCount() &lt; 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 &gt; 0) {
                                PeerNode.numberOfItems -= 1;
                            }
                            outputStream.writeBytes(&quot;0&quot; + &quot;\n&quot;);
                        }
                        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(&quot;#&quot;);
        m.setProductName(sc.next());
        m.setProductId(sc.nextInt());
        List&lt;Integer&gt; tempList = new ArrayList();
        Scanner sct = new Scanner(sc.next());
        sct.useDelimiter(&quot;,&quot;);
        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?

huangapple
  • 本文由 发表于 2020年3月4日 09:48:49
  • 转载请务必保留本文链接:https://java.coder-hub.com/60517985.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定