优化使用inputstreamreader的java多线程服务器

优化使用inputstreamreader的java多线程服务器,java,multithreading,sockets,parsing,Java,Multithreading,Sockets,Parsing,我目前正在做一个项目,在这个项目中,我必须托管一个服务器,它获取一个输入流,解析数据并将其发送到数据库。每个连接到我的服务器的客户端都会发送一个inputstream,一旦连接,它就不会停止。每个客户机都分配了一个套接字和它自己的解析器线程对象,因此服务器可以处理来自客户机的数据流。解析器对象只处理传入数据并将其发送到数据库 服务器/解析器生成器: public void generateParsers() { while (keepRunning) { try {

我目前正在做一个项目,在这个项目中,我必须托管一个服务器,它获取一个输入流,解析数据并将其发送到数据库。每个连接到我的服务器的客户端都会发送一个inputstream,一旦连接,它就不会停止。每个客户机都分配了一个套接字和它自己的解析器线程对象,因此服务器可以处理来自客户机的数据流。解析器对象只处理传入数据并将其发送到数据库

服务器/解析器生成器:

public void generateParsers() {
    while (keepRunning) {
        try {
            Socket socket = s.accept();
            // new connection
            t = new Thread(new Parser(socket));
            t.start();
        } catch (IOException e) {
            appLog.severe(e.getMessage());
        }
    }
}
解析器线程:

   @Override
    public void run() {
        while (!socket.isClosed() && socket.isConnected()) {
            try {
                BufferedReader bufReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                String line = bufReader.readLine();
                String data = "";
                if (line == null) {
                    socket.close();
                } else if (Objects.equals(line, "<DATA")) {
                    while (!Objects.equals(line, "</DATA>")) {
                        data += line;
                        line = bufReader.readLine();
                    }
                    /*
                    Send the string that was build            
                    from the client's datastream to the database
                    using the parse() function.         
                    */
                    parse(data);
                    }
                }
            } catch (IOException e) {
                System.out.println("ERROR : " + e);
            }
        }
    }
@覆盖
公开募捐{
而(!socket.isClosed()&&socket.isConnected()){
试一试{
BufferedReader bufReader=新的BufferedReader(新的InputStreamReader(socket.getInputStream());
String line=bufReader.readLine();
字符串数据=”;
如果(行==null){
socket.close();

}else if(Objects.equals(line),如果您的问题确实是在连接客户端时所做的任何事情都是昂贵的,那么您必须使用客户端队列。最简单的方法是使用具有N个最大线程数的
ExecutorService

比如说

private ExecutorService pool=Executors.newFixedThreapPool(N);
。。。 然后

Socket socket = s.accept();
pool.submit(new Parser(socket)));
这将同时将concurent客户端处理限制为N,并将超过N的任何其他客户端排队

还取决于您对数据所做的操作,例如,您始终可以将流程拆分为多个阶段

private ExecutorService pool=Executors.newFixedThreapPool(N);
  • 从客户端读取原始数据并排队处理-关闭套接字等,这样可以节省资源
  • 在单独的线程(可能是线程池)中处理数据,并将结果排队
  • 在另一个池中对结果执行一些操作(检查有效性、持久化到DB等)
  • 如果您有一些阻塞操作,如网络I/O或昂贵的操作等,这尤其有用


    在您的情况下,客户端不必等待整个后端过程完成。他只需要交付数据,因此将数据读取和解析/持久化分为不同的阶段(子任务)听起来很合理。

    如果您的问题确实是在连接客户端时所做的任何事情都很昂贵,那么您必须使用客户端队列。最简单的方法是使用最大线程数为N的
    ExecutorService

    比如说

    private ExecutorService pool=Executors.newFixedThreapPool(N);
    
    。。。 然后

    Socket socket = s.accept();
    pool.submit(new Parser(socket)));
    
    这将同时将concurent客户端处理限制为N,并将超过N的任何其他客户端排队

    还取决于您对数据所做的操作,例如,您始终可以将流程拆分为多个阶段

    private ExecutorService pool=Executors.newFixedThreapPool(N);
    
  • 从客户端读取原始数据并排队处理-关闭套接字等,这样可以节省资源
  • 在单独的线程(可能是线程池)中处理数据,并将结果排队
  • 在另一个池中对结果执行一些操作(检查有效性、持久化到DB等)
  • 如果您有一些阻塞操作,如网络I/O或昂贵的操作等,这尤其有用

    在您的案例中,客户端不必等待整个后端过程完成。他只需要交付数据,所以将数据读取和解析/持久化分为不同的阶段(子任务)听起来是合理的方法

    瓶颈主要是并发读取

    否。瓶颈是字符串连接。请使用
    StringBuffer
    StringBuilder

    当客户断开连接时,可能会出现不正确的行为。很难相信这会起作用。它不应该:

    • 您应该在套接字的生命周期内使用相同的
      BufferedReader
      ,否则可能会丢失数据
    • Socket.isClosed()
      Socket.isConnected()
      不要做你认为他们会做的事:正确的循环终止条件是
      readLine()
      返回null,或抛出
      IOException

      while ((line = bufReader.readLine()) != null)
      
    如果客户端从未断开连接,则限制并发连接的数量不可能实现任何效果。您所要完成的就是,在连接的前N个客户端之外,永远不会侦听客户端,这不可能是您想要的。“移动到下一个客户端”将永远不会发生

    瓶颈主要是并发读取

    不。瓶颈是字符串连接。请使用
    StringBuffer
    StringBuilder

    当客户断开连接时,可能会出现不正确的行为。很难相信这会起作用。它不应该:

    • 您应该在套接字的生命周期内使用相同的
      BufferedReader
      ,否则可能会丢失数据
    • Socket.isClosed()
      Socket.isConnected()
      不要做你认为他们会做的事:正确的循环终止条件是
      readLine()
      返回null,或抛出
      IOException

      while ((line = bufReader.readLine()) != null)
      

    如果客户端从未断开连接,则限制并发连接的数量不可能实现任何效果。您所要完成的只是在连接的前N个客户端之后再也不侦听客户端,这可能不是您想要的。将永远不会发生“移到下一个客户端”。

    data+=line;
    您可以重构此字符串连接使用
    StringBuilder
    进行串接。您还可以分析代码以查找是否存在任何特定瓶颈
    data+=line;
    您可以使用
    StringBuilder
    重构此字符串串接。您还可以分析代码以查找是否存在任何特定瓶颈