public void start() throws IOException, InterruptedException {
    logger.info("Starting {} processor threads", numProcessorThreads);
    for (int i = 0; i < numProcessorThreads; i++) {
      processors.add(i, new Processor(i, requestResponseChannel, metrics, sslFactory, networkConfig));
      Utils.newThread("ambry-processor-" + port + " " + i, processors.get(i), false).start();
    }

    requestResponseChannel.addResponseListener(new ResponseListener() {
      @Override
      public void onResponse(int processorId) {
        processors.get(processorId).wakeup();
      }
    });

    // start accepting connections
    logger.info("Starting acceptor threads on port {}", port);
    Acceptor plainTextAcceptor = new Acceptor(port, processors, sendBufferSize, recvBufferSize, metrics);
    this.acceptors.add(plainTextAcceptor);
    Utils.newThread("ambry-acceptor", plainTextAcceptor, false).start();

    Port sslPort = ports.get(PortType.SSL);
    if (sslPort != null) {
      SSLAcceptor sslAcceptor = new SSLAcceptor(sslPort.getPort(), processors, sendBufferSize, recvBufferSize, metrics);
      acceptors.add(sslAcceptor);
      Utils.newThread("ambry-sslacceptor", sslAcceptor, false).start();
    }
    for (Acceptor acceptor : acceptors) {
      acceptor.awaitStartup();
    }
    logger.info("Started server");
  }
A NIO socket server. The threading model is
  1 Acceptor thread that handles new connections
  N Processor threads that each have their own selector and read requests from sockets
  M Handler threads that handle requests and produce responses back to the processor threads for writing.
ambry-network/src/main/java/com/github/ambry/network/SocketServer.java