【问题标题】:Server program taking lots of CPU even when not in use [closed]服务器程序即使在不使用时也会占用大量 CPU [关闭]
【发布时间】:2013-02-07 12:18:32
【问题描述】:

我正在开发一个客户端/服务器 java 游戏。有一堆代码,我试图尽可能少地粘贴,同时仍然提供足够的内容。

当我第一次启动服务器时,它不需要 CPU。当我的第一个游戏客户端连接时,它会跃升至 25%(这似乎相当高,但这还不是我主要关心的问题)。问题是,即使客户端断开连接,服务端应用的 CPU 使用率仍然保持在 25%。

服务器从客户端获取一个名字,并不断地从玩家那里接收 x、y 坐标。

这是我的实际服务器的代码,一旦服务器启动就会运行:(我事先为过多的缩进道歉)

 TCPServer(int port) {
                try
                {
                        tcpSock = new ServerSocket(port);
                        int z = 0;
                        while(true)
                        {
                                Socket sock = tcpSock.accept();
                                sock.setKeepAlive(true);  
                                clientList.addElement(new TcpClient(sock));
                                clientList.get(z).cr.start();
                                clientList.get(z).cw.start();
                                clientList.get(z).packs.addElement("?");
                                while(!clientList.get(z).cr.nameRecieved)
                                {
                                //do nothing untill client has provided it's name
                                }
                                playerList.addElement(new player(sock.getInetAddress(), clientList.get(z).cr.playerName));                                     
                                playerList.get(z).id=z;
                                playerList.get(z).name=clientList.get(z).cr.playerName;
                                clientList.get(z).packs.addElement("2 " + z);
                                for(int j =0; j<playerList.size();j++)
                                    {
                                   String status;
                                   if(playerList.get(j).Connected)
                                       status = "1";
                                   else
                                       status = "0";

                                        addToQueue("3 " + playerList.get(j).id + " "
                                                + playerList.get(j).name + " " + playerList.get(j).x + " " + playerList.get(j).y + " " + 
                                                playerList.get(j).area + " " + status + " " );                     
                                    }
                                z++;
                                addToQueue("4 " + z);
                        }    
                }

                catch (IOException e) {   
                        System.out.print(e);   
                }   
        }

这是为每个客户端运行的代码。为了便于阅读,我已经注释掉了大部分内容,代码只是计算和更新各种位置信息。我认为这个问题发生在这个班级的某个地方。

  public class TcpClient {
                Socket sock;
                ObjectInputStream in;
                ObjectOutputStream out;
                ClientRead cr;
                ClientWrite cw;
                public Vector<String> packs = new Vector<String>();
                 TcpClient(Socket s) {
                        this.sock = s;
                        try
                        {
                            sock.setKeepAlive(true);
                        }
                        catch(Exception e)
                        {
                            System.out.print(e);
                        }
                        cr = new ClientRead();
                        cw = new ClientWrite();
                }
                public class ClientRead extends Thread {
                     public boolean nameRecieved = false;
                     public boolean reading = true;
                String playerName;
                    public void run(){
                        try{
                            in  = new ObjectInputStream(sock.getInputStream());
                            while(sock.isConnected() && reading)
                            {
                               //code to retrieve and update user location
                            }
                        }
                        catch(Exception e){
                                System.out.print(e);
                    }
                }
        }

最后是一个向客户端写入信息的简短类:

public class ClientWrite extends Thread {
                 public boolean writing = true;
                    public void run() {
                        try{

                            out = new ObjectOutputStream(sock.getOutputStream());
                            out.flush();
                            while(sock.isConnected() && writing)
                            {
                                out.flush();
                                while(!packs.isEmpty())
                                {
                                    out.writeObject(packs.firstElement());
                                    System.out.print(packs.firstElement());
                                    packs.remove(0);
                                    out.flush();
                                }
                            }

                        }
                        catch(Exception e)
                        {
                            System.out.print(e);
                        }
                    }
                }

我知道有大量代码,但如果有人看到任何立即跳出的东西(尤其是线程),就可以解释我得到的行为。回顾一下,服务器保持在 0% cpu 直到客户端连接。在第一个客户端连接后,无论再连接多少,它都保持在 25%-30% 的 CPU 上。但是,当所有客户端都断开连接时,CPU 会停留在 25%-30%,而不是回到 0。

【问题讨论】:

  • 顺便说一句,25% 的 CPU 可能是四核处理器中一个核心的 100%。该线程正在尽可能多地使用 CPU 时间。
  • @BevynQ 线程不“需要轮询样式”。它们使使用阻塞模型成为可能。这就是你使用它们的原因。

标签: java performance sockets tcp tcpclient


【解决方案1】:

问题出在这里:

while(!clientList.get(z).cr.nameRecieved)
{
    //do nothing untill client has provided it's name
}

这是一个自旋循环,会抽 CPU。你做这一切都是错的。一旦接受了套接字,就必须启动一个新线程来处理它。 那个线程应该阻塞直到客户端提供它的名字作为你的协议握手的一部分,然后更新你的数据结构。除了接受连接和启动线程之外,accept 循环不应该做任何事情。

【讨论】:

  • +1 高效。
  • 谢谢,我会调查一下。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-29
  • 2014-05-12
  • 1970-01-01
相关资源
最近更新 更多