簡體   English   中英

Java套接字占用太多的CPU和虛擬內存

[英]java socket takes too much cpu% and virtual memory

我已經開發了一個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();
}

該問題我該怎么辦? 提前致謝。

您似乎直接在套接字的輸入流上進行了許多小讀操作。 如果使用緩沖的輸入流包裝輸入流,則應該獲得更好的性能。

Oracle Java教程中討論了緩沖流的使用

輸出端看起來更好一些。 您正在組裝數據包,並將其寫入較大的寫入調用中。 但是,我仍然對此表示懷疑,並且可能沒有必要進行某些flush調用。


正如EJP指出的那樣,您的I / O代碼很脆弱,因為您沒有考慮“另一端”已關閉套接字的可能性。 這將導致read和等效調用返回,而不讀取任何內容。

請注意, read方法返回已讀取的字節(或字符)數,如果檢測到“流的末尾”,則返回-1。 您的代碼完全忽略了返回值。

這可能是導致性能問題的原因; 例如,如果線程反復調用處於“流結束”狀態的套接字上的read


代碼的另一個可能問題是,每次accept()調用成功時,您的listen方法都將創建一個全新的Thread

  • 如果有很多客戶端連接,那么會有很多線程,這會導致大量資源使用。
  • 如果客戶端沒有斷開連接和/或服務器沒有注意到它們已斷開連接,則資源將泄漏,並且服務器將永遠不會將其退還。

如果您正在泄漏線程,而這些線程處於空閑狀態,則它們正在浪費內存。 (線程堆棧通常為1Mb左右。)如果它們不處於空閑狀態(例如,由於讀取代碼中的錯誤……例如未正確處理“流的結尾”條件),那么您也將浪費CPU。

@chanjaster建議使用具有固定大小的線程池的執行程序。 這可能在兩個方面有所幫助:

  • 它防止應用程序使用無數線程。
  • 在線程不再活動之后,它將回收線程...這減少了開銷。

但是,如果您遇到資源泄漏的問題,線程池將無法解決此問題。 確實,可能會發生的是新連接剛剛凍結。 (它們進入任務隊列,等待輔助線程將其拾取。這永遠不會發生。)

暫無
暫無

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

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