class App {

  private NioReactor reactor;
  private final List<AbstractNioChannel> channels = new ArrayList<>();
  private final Dispatcher dispatcher;

  /**
   * Creates an instance of App which will use provided dispatcher for dispatching events on
   * reactor.
   *
   * @param dispatcher the dispatcher that will be used to dispatch events.
   */
  public App(Dispatcher dispatcher) {
    this.dispatcher = dispatcher;
  }

  /**
   * App entry.
   */
  public static void main(String[] args) throws IOException {
    new App(new ThreadPoolDispatcher(2)).start();
  }

  /**
   * Starts the NIO reactor.
   *
   * @throws IOException if any channel fails to bind.
   */
  public void start() throws IOException {<FILL_FUNCTION_BODY>}

  /**
   * Stops the NIO reactor. This is a blocking call.
   *
   * @throws InterruptedException if interrupted while stopping the reactor.
   * @throws IOException          if any I/O error occurs
   */
  public void stop() throws InterruptedException, IOException {
    reactor.stop();
    dispatcher.stop();
    for (var channel : channels) {
      channel.getJavaChannel().close();
    }
  }

  private AbstractNioChannel tcpChannel(int port, ChannelHandler handler) throws IOException {
    var channel = new NioServerSocketChannel(port, handler);
    channel.bind();
    channels.add(channel);
    return channel;
  }

  private AbstractNioChannel udpChannel(int port, ChannelHandler handler) throws IOException {
    var channel = new NioDatagramChannel(port, handler);
    channel.bind();
    channels.add(channel);
    return channel;
  }
}

    /*
     * The application can customize its event dispatching mechanism.
     */
    reactor = new NioReactor(dispatcher);

    /*
     * This represents application specific business logic that dispatcher will call on appropriate
     * events. These events are read events in our example.
     */
    var loggingHandler = new LoggingHandler();

    /*
     * Our application binds to multiple channels and uses same logging handler to handle incoming
     * log requests.
     */
    reactor
        .registerChannel(tcpChannel(16666, loggingHandler))
        .registerChannel(tcpChannel(16667, loggingHandler))
        .registerChannel(udpChannel(16668, loggingHandler))
        .registerChannel(udpChannel(16669, loggingHandler))
        .start();
  
<no_super_class>