套接字监听器是KILLING我的CPU,如何提高我的代码性能?

时间:2013-02-27 20:57:58

标签: java multithreading sockets listener port

我已经实现了一个Socket Listener来读取从GPS发送的数据,但它占据了我90%的CPU。我知道我的代码导致了这一点,但我无法看到。

这是我的主要课程:

public class PortToDB {

    ServerSocket serverSocket = null;

    public void listenSocket(){
        try{
            serverSocket = new ServerSocket(50000);
        } catch (IOException e) {
            System.out.println("Could not listen on port 50000. " + e);
            System.exit(-1);
        }

        while(true){
            GPSData gd;
            try{
                gd = new GPSData(serverSocket.accept());
                Thread t = new Thread(gd);
                t.start();
            } catch (IOException e) {
                System.out.println("Accept failed: 50000. " + e);
                System.exit(-1);
            }
        }
    }

    public static void main(String[] args) {    
        PortToDB portToDb = new PortToDB();
        portToDb.listenSocket();
    }
}

这是我的Runnable类:

class GPSData implements Runnable {

    private Socket client;
    DBHandler dbhandler = new DBHandler();

    GPSData(Socket client) { this.client = client; }

    public void run(){
        String line;
        BufferedReader in = null;

    try{
        in = new BufferedReader(new InputStreamReader(client.getInputStream()));
    } catch (IOException e) {
        System.out.println("in or out failed");
        System.exit(-1);
    }

    while(true){
      try{
          if((line = in.readLine()) != null){
              dbhandler.dbInsert(line);
          }
      } catch (IOException e) {
          System.out.println("Read failed");
          System.exit(-1);
      }
    }
  }
}

3 个答案:

答案 0 :(得分:6)

如果readLine()返回null,则必须关闭套接字,退出读取循环,并忘记该客户端。你在EOS旋转。

答案 1 :(得分:4)

不是为每个传入请求创建新线程,而是使用线程池:

private ExecutorService executor = Executors.newFixedThreadPool(15);

// ...

gd = new GPSData(serverSocket.accept());
executor.submit(gd);

这样,您将消除在接收请求时创建无限制线程的开销,而不是在打开套接字端口以接收请求之前创建有限的线程。


另外,正如@EJB所说,只要从null收到readLine()作为流结束(EOS)的指示符,就退出客户端for循环。

答案 2 :(得分:0)

感谢所有回答我问题的人。

我通过结合Eng.Fouad和EJP的建议解决了这个问题:

这是我在代码中更改的内容:

执行人:

    private ExecutorService executor = Executors.newFixedThreadPool(15);

    try{
        gd = new GPSData(serverSocket.accept());
        executor.submit(gd);
    }

循环控制:

    try{            
        while((line = in.readLine()) != null){         
        dbhandler.dbInsert(line);
        }
    }

现在这个过程一直停留在0%:)。

感谢EJP和Eng.Fouad。