ThreadPerChannelEventLoopGroup extends AbstractEventExecutorGroup implements EventLoopGroup { @Override public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { long deadline = System.nanoTime() + unit.toNanos(timeout); for (EventLoop l: activeChildren) { for (;;) { long timeLeft = deadline - System.nanoTime(); if (timeLeft <= 0) { return isTerminated(); } if (l.awaitTermination(timeLeft, TimeUnit.NANOSECONDS)) { break; } } } for (EventLoop l: idleChildren) { for (;;) { long timeLeft = deadline - System.nanoTime(); if (timeLeft <= 0) { return isTerminated(); } if (l.awaitTermination(timeLeft, TimeUnit.NANOSECONDS)) { break; } } } return isTerminated(); } protected  ThreadPerChannelEventLoopGroup(); protected  ThreadPerChannelEventLoopGroup(int maxChannels); protected  ThreadPerChannelEventLoopGroup(int maxChannels, ThreadFactory threadFactory, Object... args); protected  ThreadPerChannelEventLoopGroup(int maxChannels, Executor executor, Object... args); @Override Iterator<EventExecutor> iterator(); @Override @SuppressWarnings("unchecked") Set<E> children(); @Override EventLoop next(); @Override Future<?> shutdownGracefully(long quietPeriod, long timeout, TimeUnit unit); @Override Future<?> terminationFuture(); @Override @Deprecated void shutdown(); @Override boolean isShuttingDown(); @Override boolean isShutdown(); @Override boolean isTerminated(); @Override boolean awaitTermination(long timeout, TimeUnit unit); @Override ChannelFuture register(Channel channel); @Override ChannelFuture register(Channel channel, ChannelPromise promise);  }
@Test public void testTerminationFutureSuccessReflectively() throws Exception { Field terminationFutureField = ThreadPerChannelEventLoopGroup.class.getDeclaredField("terminationFuture"); terminationFutureField.setAccessible(true); final Exception[] exceptionHolder = new Exception[1]; for (int i = 0; i < 2; i++) { ThreadPerChannelEventLoopGroup loopGroup = new ThreadPerChannelEventLoopGroup(64); Promise<?> promise = new DefaultPromise<Void>(GlobalEventExecutor.INSTANCE) { @Override public Promise<Void> setSuccess(Void result) { try { return super.setSuccess(result); } catch (IllegalStateException e) { exceptionHolder[0] = e; throw e; } } }; terminationFutureField.set(loopGroup, promise); runTest(loopGroup); } GlobalEventExecutor.INSTANCE.awaitTermination(100, TimeUnit.MILLISECONDS); assertNull(exceptionHolder[0]); }