[英]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.