title: Collect data from different threads
body: <p>I have implemented a basic TCP client and server. The client sends a command from an input stream. The server processes received message and replies to the client. </p>
  
  <p>I would like to test my client-server solution in the following manner:</p>
  
  <ol>
  <li>Create multiple client threads;</li>
  <li>Each client thread will read commands from the file and send them to a server;</li>
  <li>After a server's reply, each client must collect the reply to a list;</li>
  </ol>
  
  <p>I would like to seek any code review and any suggestions (I would appreciate any examples) on how to collect a server replies to a list from each client thread. Currently, I am not able to collect all replies from all client threads in  <code>List&lt;String&gt; messages</code></p>
  
  <p>Class <code>Client</code> spawns a fixed number of <code>ClientTask</code></p>
  
  <pre><code>public class Client {
  private static Logger logger = Logger.getLogger(Client.class);
  private File configs;
  private InputStream inputStream;
  private int port;
  private String ip;
  
  
  public Client(File file, InputStream inputStream) {
      this.configs = file;
      this.inputStream = inputStream;
      Map&lt;String, Object&gt; configs = ConfigLoader.loadXMLConfigsFromFile(file);
      this.port = (Integer) configs.get("port");
      this.ip = (String) configs.get("ip");
  }
  
  //
  public void start(int numberOfThreads, List&lt;String&gt; messages) throws InterruptedException {
      for (int i = 0; i &lt; numberOfThreads; i++) {
          List&lt;String&gt; collectedServerReply = Collections.synchronizedList(new ArrayList&lt;&gt;());
          try {
              Thread clientThread = new Thread(
                      new ClientTask(port, ip)
                              .setInputStream(new FileInputStream("commands.txt"))
                              .setReplyListener(message -&gt; {
                                  //messages.add(message.receive().getMessage());
                                  collectedServerReply.add(message.receive().getMessage());
                                  //System.out.println("current stack size: " + messages.size());
                              }));
              clientThread.start();
              System.out.println("finished client thread");
          } catch (IOException e) {
              logger.error("Exception occurred while reading from System.in. Exception: ", e);
          }
          messages.addAll(collectedServerReply);
      }
  }
  }
  </code></pre>
  
  <p>The Client class has a setter that accepts any instance that implements the ReplyListerner interface. The latter server as an abstraction to collect a reply data:</p>
  
  <pre><code>public interface ReplyListener {
  
      void onReply(Message message) throws IOException;
  }
  </code></pre>
  
  <p>I cannot collect all server replies in the method <code>public void start(int numberOfThreads, List&lt;String&gt; messages)</code>. However, when I simply do the following: </p>
  
  <pre><code> Thread clientThread = new Thread(
                          new ClientTask(port, ip)
                                  .setInputStream(new FileInputStream("commands.txt"))
                                  .setReplyListener(message -&gt; {
                                      System.out.println(message.receive().toString());}));
  </code></pre>
  
  <p>I could see the appropriate server replies in my <code>System.in</code></p>
  
  <p>Where did I make a mistake and how can I achieve my goal of collecting server replies? </p>
  
  <p><strong>EDIT:</strong></p>
  
  <p>How do I use my implementations:</p>
  
  <pre><code>public static void main(String[] args) throws IOException, InterruptedException {
      List&lt;String&gt; collectedMessages = Collections.synchronizedList(new ArrayList&lt;&gt;());
  
      Thread serverThread = new Thread(new ServerLauncher(new File("config.xml")));
      serverThread.setName("server_thread");
      serverThread.start();
      new Client(new File("config.xml"), new FileInputStream("commands.txt")).start(1, collectedMessages);
      System.out.println("Collected output ...");
      for (int i = 0; i &lt; collectedMessages.size(); i++) {
          System.out.println(collectedMessages.get(i));
      }
  }
  </code></pre>