java socket需要太多的cpu%和虚拟内存

时间:2014-11-13 13:01:59

标签: java multithreading sockets memory-management cpu-usage

我开发了一个java套接字,但它需要太多的CPU和虚拟内存。 你能告诉我我的代码中有什么问题吗?

private void listen() {
    try {
        serverSocket = new ServerSocket(port);

        System.out.println("Server socket listening on port: " + port);
        System.out.println("Waiting for connections...");

        while(true) {
            // accept the connection
            Socket socket = serverSocket.accept();
            socket.setSoTimeout(30000);
            System.out.println("Got connection");
            // start processing the connection
            Thread connectionManager = new Thread(new Elevator(socket, socket.getInputStream()));//new Thread(new ConnectionManager(socket, odometer));
            connectionManager.start();
        }
    } catch (IOException exc) {
        System.out.println(Listener.class.getName() + ": " + exc.getMessage());
    }
}
电梯课程中的

我有这个:

public class Elevator implements Runnable 
{

private String imei;
private Socket socket;
private InputStream is;
private PrintWriter out;
private OutputStream ds;
private int packetL;
private long timestamp;
dbElevatorManipulate dbElevator;
private String[] allCards = null;
private String[] insCards = null;
private String[] upddelCards = null;
private String[] config = null;


public Elevator(Socket socket, InputStream is) {
    this.socket = socket;
    this.is = is;
    initializeOutputStream(socket);
}

private void initializeOutputStream(Socket socket) {
    try {
        ds = socket.getOutputStream();
    } catch (IOException e) {
        e.printStackTrace();
    }
    out = new PrintWriter(ds, true);
}


@Override
public void run(){

    int codecL = 1;
    int imeiL = 16;

    String codecID = "";
    String imeiFromBoard = "";

    byte[] codecBuffer = new byte[codecL];
    byte[] imeiBuffer = new byte[imeiL];

    try{
        // Read codec ID.
        is.read(codecBuffer, 0, codecL);
        codecID = byteToString(codecBuffer);
        //System.out.println("Codec ID   : " + codecID);

        // Read imei.
        is.read(imeiBuffer, 0, imeiL);
        imeiFromBoard = byteToString(imeiBuffer);

        if (codecID.equals("2")) {

            byte[] crc = new byte[2];
            is.read(crc);

            byte[] cnnpacket = new byte[codecL + imeiL];

            cnnpacket[0] = codecBuffer[0];
            for (int i = 1; i < cnnpacket.length; i++) {
                cnnpacket[i] = imeiBuffer[i-1];
            }

            if(DataLayer.checksum(cnnpacket, crc))
            {

                try {
                    ds.write(1);
                    ds.flush();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            else
            {

                try {
                    ds.close();
                    is.close();
                    dbElevator.disconnect();
                    socket.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
                return;
            }
        }
    }
    catch(Exception ex)
    {
        System.out.println("Error: " + ex.getMessage());
    }

    imeiFromBoard = imeiFromBoard.substring(1, imeiFromBoard.length());
    imei = imeiFromBoard;
    System.out.println("got connection with imei:" + imei);
    dbElevator = new dbElevatorManipulate(imei);
    dbElevator.connect();
    try{
            while(true){        
            byte[] packet = new byte[1024];
            int i = 0;
            int byteread = is.read(packet);

            if(byteread == -1) continue;
            int cmdL = 1;
            int dataLen = 2;
            byte[] cmdBuffer = new byte[cmdL];
            byte[] lengthBuffer = new byte[dataLen];

            // Read and Print cmd.
            cmdBuffer[0] = packet[0];

            if(cmdBuffer[0] > 9 || cmdBuffer[0] < 0){
                continue;
            }

            // Read and Print data length.
            lengthBuffer[0] = packet[1];
            lengthBuffer[1] = packet[2];

            packetL = Integer.parseInt(DataLayer.byteToString(lengthBuffer));

            // Reading a printing the packet .
            byte[] packetBuffer = new byte[packetL];
            int pcnt = 3;
            while(packetL-- > 0)
            {
                packetBuffer[pcnt - 3] = packet[pcnt];
                pcnt++;

            }
            String packetData = DataLayer.byteToString(packetBuffer);
            // Reading and printing crc
            int crcL = 2;
            byte[] crcBuffer = new byte[crcL];
            crcBuffer[0] = packet[pcnt];
            crcBuffer[1] = packet[pcnt + 1];

            if (DataLayer.checksum(packetBuffer, crcBuffer)) {
                System.out.println("Packet: OK");

                switch(cmdBuffer[0])
                {
                    case 0: 
                        int nrOfPackets = dbElevator.getNrOfTotalPackets();
                        int nCrc = DataLayer.crc16(new byte[] {(byte)nrOfPackets});
                        byte[] sendPacket = new byte[3];
                        sendPacket[0] = (byte)nrOfPackets;
                        sendPacket[1] = (byte)((nCrc >> 8) & 0xff); // hight byte of crc
                        sendPacket[2] = (byte)(nCrc & 0xff);        // low byte of crc

                        ds.write(sendPacket);
                        ds.flush();
                        allCards = dbElevator.getTotalCards().split(",");
                        break;
                    case 1: 
                        int PacketNo = Integer.parseInt(packetData);
                        if(allCards != null)
                            sendAllPacket(PacketNo);
                        break;
                    case 2: 
                        int nrOfUpdPackets = dbElevator.getUpdDelCardsNo();
                        int updCrc = DataLayer.crc16(new byte[] {(byte)nrOfUpdPackets});
                        byte[] sendUpdPacket = new byte[3];
                        sendUpdPacket[0] = (byte)nrOfUpdPackets;
                        sendUpdPacket[1] = (byte)((updCrc >> 8) & 0xff); // hight byte of crc
                        sendUpdPacket[2] = (byte)(updCrc & 0xff);       // low byte of crc

                        ds.write(sendUpdPacket);
                        ds.flush();
                        upddelCards = dbElevator.getUpdDelCards().split(",");
                        break;
                    case 3:
                        int updPacketNo = Integer.parseInt(packetData);
                        sendUpdDelPacket(updPacketNo);
                        break;
                    case 4: 
                        int nrOfInsPackets = dbElevator.getInsertedCardsNo();
                        int insCrc = DataLayer.crc16(new byte[] {(byte)nrOfInsPackets});
                        byte[] sendInsPacket = new byte[3];
                        sendInsPacket[0] = (byte)nrOfInsPackets;
                        sendInsPacket[1] = (byte)((insCrc >> 8) & 0xff); // hight byte of crc
                        sendInsPacket[2] = (byte)(insCrc & 0xff);       // low byte of crc

                        ds.write(sendInsPacket);
                        ds.flush();
                        insCards = dbElevator.getInsertedCards().split(",");
                        break;
                    case 5: 
                        int insPacket = Integer.parseInt(packetData);
                        sendInsPacket(insPacket);
                        break;

                    case 6: 
                        insertCheckInIntoDB(packetBuffer);
                        break;
                    case 7:
                        config  = dbElevator.getConfig().split(",");
                        sendConfig(config);
                        break;
                    case 8: //log cards and close connection
                        try {
                                if(insCards != null && insCards.length > 2)
                                {
                                    dbElevator.resetActionForIns(insCards);
                                    dbElevator.LogSent_insCards(insCards);

                                }
                                if(upddelCards != null && upddelCards.length > 2)
                                {   
                                    dbElevator.resetActionForUpd(upddelCards);
                                    dbElevator.LogSent_updCards(upddelCards);
                                }
                                if(allCards != null && allCards.length > 2)
                                {
                                    dbElevator.resetActionForAll(allCards);
                                    dbElevator.LogSent_allCards(allCards);
                                }
                                if(config != null && config.length > 0)
                                {
                                    dbElevator.ConfigSent();
                                }

                                ds.close();
                                is.close();
                                dbElevator.disconnect();
                                System.out.println("database disconnected");
                                socket.close();
                                System.out.println("socket closed.");
                                return;

                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        break;
                    case 9:
                        int sendConfig = dbElevator.getSendConfig();

                        int sendConfigCRC = DataLayer.crc16(new byte[] {(byte)sendConfig});
                        byte[] sendConfigConfirm = new byte[3];
                        sendConfigConfirm[0] = (byte)sendConfig;
                        sendConfigConfirm[1] = (byte)((sendConfigCRC >> 8) & 0xff); 
                        sendConfigConfirm[2] = (byte)(sendConfigCRC & 0xff);        
                        ds.write(sendConfigConfirm);
                        ds.flush();
                        break;
                }

            }else{
                //System.out.println("Packet: error");
                ds.write(0x00);
                ds.flush();
            }
            }   
        }catch(IOException e){
            e.printStackTrace();
        }
    finally{
        try {
            ds.close();
            System.out.println("ds closed.");
            is.close();
            System.out.println("is closed.");
            dbElevator.disconnect();
            System.out.println("db disconnected.");
            socket.close();
            System.out.println("socket closed.");
            //break;
        } catch (IOException e1) {
            e1.printStackTrace();
        }
    }
}

private void sendConfig(String[] config) throws IOException {
    byte[] packet = new byte[16*3];
    for(int c = 0, i = 0; c<32; c++)
    {
        if(c<16){
            int temp = Integer.parseInt(config[c],2);
            packet[i++] = (byte)((temp >> 8) & 0xff);
            packet[i++] = (byte)(temp & 0xff);
        }
        else
        {
            packet[i++] = (byte)(Integer.parseInt(config[c]) & 0xff);
        }
    }

    int crc = DataLayer.crc16(packet);

    byte[] txPacket = new byte[3*16 + 2];

    for(int i = 0; i<16*3; i++)
    {
        txPacket[i] = packet[i];
    }

    txPacket[16*3] = (byte)((crc >> 8) & 0xff);
    txPacket[16*3 + 1] = (byte)((crc) & 0xff);
    ds.write(txPacket);
    ds.flush();
}

private void insertCheckInIntoDB(byte[] packetData){

    String values = "";
    try{
        for(int i = 0; i<packetData.length; i+=8)
        {

            byte[] siteCode = new byte[1];
            siteCode[0] = packetData[i];

            byte[] siteNo = new byte[2];
            siteNo[0] = packetData[i + 1];
            siteNo[1] = packetData[i + 2];

            byte[] Floor = new byte[1];
            Floor[0] = (byte)(packetData[i + 3] >> 4 & 0xf);

            byte[] Valide = new byte[1];
            Valide[0] = (byte)(packetData[i + 3] & 0xf);

            byte[] timestamp = new byte[4];
            timestamp[0] = packetData[i + 4];
            timestamp[1] = packetData[i + 5];
            timestamp[2] = packetData[i + 6];
            timestamp[3] = packetData[i + 7];
            if(Long.parseLong(DataLayer.byteToString(timestamp)) < 1410000000)
            {
                continue;
            }
            values += "(" + imei + ",";
            values += DataLayer.byteToString(siteCode) + ",";
            values += DataLayer.byteToString(siteNo) + ",";
            values += DataLayer.byteToString(Floor) + ",";
            values += DataLayer.byteToString(Valide) + ",";
            values += DataLayer.byteToString(timestamp) + "),";
        }
        values = values.substring(0, values.length()-1);
        if(dbElevator.insertCheckIn(values))
        {
            ds.write(1);
            ds.flush();
            return;
        }
        else
        {
            try {
                ds.write(0);
                ds.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }   
    }
    catch(Exception ex){
        try {
            ds.write(0);
            ds.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

private void sendUpdDelPacket(int updPacketNo) throws IOException {
    byte[] packet = new byte[38*6];

    for(int i = 0, c = 38*4*updPacketNo; i<38*6; i+=6, c+=4)
    {
        if(c + 3 < upddelCards.length)
        {
            packet[i]   = (byte)Integer.parseInt(upddelCards[c]);

            //System.out.println(upddelCards[c+1]);
            packet[i+1] = (byte)(Integer.parseInt(upddelCards[c+1]) >> 8 & 0xff);
            packet[i+2] = (byte)(Integer.parseInt(upddelCards[c+1]) & 0xff);
            packet[i+3] = (byte)(Integer.parseInt(upddelCards[c+2], 2) >> 8 & 0xff);
            packet[i+4] = (byte)(Integer.parseInt(upddelCards[c+2], 2) & 0xff);
            packet[i + 5]   = (byte)Integer.parseInt(upddelCards[c + 3]);
        }
        else
        {
            packet[i] = 0;
            packet[i+1] = 0;
            packet[i+2] = 0;
            packet[i+3] = 0;
            packet[i+4] = 0;
            packet[i+5] = 0;
        }
    }

    int crc = DataLayer.crc16(packet);

    byte[] txPacket = new byte[38*6 + 2];

    for(int i = 0; i<38*6; i++)
    {
        txPacket[i] = packet[i];
    }
    txPacket[38*6] = (byte)((crc >> 8) & 0xff);
    txPacket[38*6 + 1] = (byte)((crc) & 0xff);
    ds.write(txPacket);
    ds.flush();
}

private void sendInsPacket(int packetNo) throws IOException {

    byte[] packet = new byte[46*5];
    for(int i = 0, c = 46*3*packetNo; i< 46*5; i+=5, c+=3)
    {
        if(c + 2 < insCards.length)
        {
            packet[i]   = (byte)Integer.parseInt(insCards[c]); 

            packet[i+1] = (byte)(Integer.parseInt(insCards[c+1]) >> 8 & 0xff);
            packet[i+2] = (byte)(Integer.parseInt(insCards[c+1]) & 0xff);
            packet[i+3] = (byte)(Integer.parseInt(insCards[c+2], 2) >> 8 & 0xff);
            packet[i+4] = (byte)(Integer.parseInt(insCards[c+2], 2) & 0xff);
        }
        else
        {
            packet[i]   = 0;
            packet[i+1] = 0;
            packet[i+2] = 0;
            packet[i+3] = 0;
            packet[i+4] = 0;
        }

    }

    int crc = DataLayer.crc16(packet);

    byte[] txPacket = new byte[46*5 + 2];

    for(int i = 0; i<46*5; i++)
    {
        txPacket[i] = packet[i];
    }
    txPacket[46*5] = (byte)((crc >> 8) & 0xff);
    txPacket[46*5 + 1] = (byte)((crc) & 0xff);
    ds.write(txPacket);
    ds.flush();
}

private void sendAllPacket(int packetNo) throws IOException {

    byte[] packet = new byte[46*5];
    for(int i = 0, c = 46*3*packetNo; i< 46*5; i+=5, c+=3)
    {
        if(c + 2 < allCards.length)
        {
            packet[i]   = (byte)Integer.parseInt(allCards[c]);

            packet[i+1] = (byte)(Integer.parseInt(allCards[c+1]) >> 8 & 0xff);
            packet[i+2] = (byte)(Integer.parseInt(allCards[c+1]) & 0xff);
            packet[i+3] = (byte)(Integer.parseInt(allCards[c+2], 2) >> 8 & 0xff);
            packet[i+4] = (byte)(Integer.parseInt(allCards[c+2], 2) & 0xff);
        }
        else
        {
            packet[i]   = 0;
            packet[i+1] = 0;
            packet[i+2] = 0;
            packet[i+3] = 0;
            packet[i+4] = 0;
        }

    }

    int crc = DataLayer.crc16(packet);

    byte[] txPacket = new byte[46*5 + 2];

    for(int i = 0; i<46*5; i++)
    {
        txPacket[i] = packet[i];
    }
    txPacket[46*5] = (byte)((crc >> 8) & 0xff);
    txPacket[46*5 + 1] = (byte)((crc) & 0xff);
    ds.write(txPacket);
    ds.flush();
}

private static String byteToString(byte[] buffer) {
    StringBuilder s = new StringBuilder();
    for (byte b : buffer) {
        s.append((char) b);
    }
    return s.toString();
}

我该怎么办这个问题? 提前谢谢。

1 个答案:

答案 0 :(得分:4)

您似乎直接在套接字的输入流上执行了大量小读取操作。如果使用缓冲的输入流包装输入流,则应该获得更好的性能。

Oracle Java Tutorial.

中讨论了缓冲流的使用

输出端看起来好一点。您正在组装数据包,并将它们写入大(呃)写入调用中。但是,我仍然对此表示怀疑......并且有些flush次呼叫的可能性是不必要的。


正如EJP指出的那样,您的I / O代码很脆弱,因为您没有考虑“另一端”关闭套接字的可能性。这将导致read和等效的调用返回而不读取任何内容。

请注意,read方法返回已读取的字节数(或字符数),如果检测到“流结束”,则返回-1。您的代码完全忽略了返回值。

这可能是导致性能问题的原因;例如如果一个线程在一个处于“流结束”状态的套接字上重复调用read


您的代码存在另一个可能的问题,即每次listen调用成功时,您的Thread方法都会创建一个全新的accept()

  • 如果你有很多客户端连接,会有很多线程,这导致大量的资源使用。
  • 如果客户端没有断开连接和/或服务器没有注意到它们已断开连接,那么资源就会泄漏,您的服务器将永远不会回复它们。

如果你正在泄漏线程,并且这些线程处于空闲状态,那么它们就会浪费内存。 (线程堆栈通常是1Mb左右。)如果它们没有空闲(例如,由于您的读取代码中的错误...就像没有正确处理“流结束”条件那样)那么您也将浪费CPU。

@chanjaster建议使用具有固定大小的线程池的执行程序。这可能有助于在几个方面:

  • 它使用无限数量的线程阻止应用程序。
  • 它会在线程不再活动后进行回收...这样可以减少开销。

但是,如果您遇到资源泄漏问题,则线程池无法解决此问题。实际上,可能会发生的事情是新的连接只会冻结。 (他们进入任务队列,等待工作线程接收它们。这种情况永远不会发生。)