簡體   English   中英

帶有 TCP 套接字的 Java 應用程序正在使用 100% 的 CPU

[英]Java application with TCP sockets is using 100% of CPU

服務器必須持續監聽傳入的連接並對接收到的數據執行一些邏輯。 每次運行應用程序時,CPU 使用率都在 90% 以上。 早些時候我認為 while 循環可能正在旋轉(忙等待),但 readLine() 應該是一個阻塞調用,所以我不認為是這種情況。 任何幫助表示贊賞! 以下是服務器代碼:

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();
         }
    }

編輯:添加了 deserialize() 方法

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;
    }

編輯 2:將 deserialize() 更改為使用 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;
}

編輯:更新服務器代碼:

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 類:

 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;
}

您是否為每個新的客戶端連接使用不同的線程,而且這種代碼永遠不會占用如此高的 CPU 負載百分比。 是否還有其他一些在后台運行的功能? 編輯:也許你可以嘗試這樣的事情?

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(); 
    } 
} 

這有幫助嗎?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM