problem:
- NioEventLoop role in the end is what? Where it was used?
- NioEventLoop and ServerBootstrap and EventLoopGroup we created at the beginning of what is the relationship?
- NioEventLoop and NioChannel how transfer (reasonable, a channel should be assigned a NioEventLoop)
- NioEventLoop works
Outline
要知道 NioEventLoop 就必须从 EventLoopGroup 说起,以下是它们的类结构图。
We are in the process of analyzing netty handled by the server, there is a createChannel () procedure, and then call the group (). Next () method returns a NioEventLoop, the rest of the stuff on to this NioEventLoop to deal with the actual included in EventLoopGroup this is a NioEventLoop array, which is to perform the perpetrators process.
Source code analysis
EventLoopGroup parent MultithreadEventLoopGroup analysis
public abstract class MultithreadEventLoopGroup extends MultithreadEventExecutorGroup implements EventLoopGroup { private static final InternalLogger logger = InternalLoggerFactory.getInstance(MultithreadEventLoopGroup.class); private static final int DEFAULT_EVENT_LOOP_THREADS; //默认EventLoopThreads处理线程数 static { DEFAULT_EVENT_LOOP_THREADS = Math.max(1, SystemPropertyUtil.getInt( "io.netty.eventLoopThreads", Runtime.getRuntime().availableProcessors() * 2)); if (logger.isDebugEnabled()) { logger.debug("-Dio.netty.eventLoopThreads: {}", DEFAULT_EVENT_LOOP_THREADS); } } /** * @see {@link MultithreadEventExecutorGroup#MultithreadEventExecutorGroup(int, Executor, Object...)} */ protected MultithreadEventLoopGroup(int nThreads, Executor executor, Object... args) { super(nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads, executor, args); } /** * @see {@link MultithreadEventExecutorGroup#MultithreadEventExecutorGroup(int, ThreadFactory, Object...)} */ protected MultithreadEventLoopGroup(int nThreads, ThreadFactory threadFactory, Object... args) { super(nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads, threadFactory, args); } @Override protected ThreadFactory newDefaultThreadFactory() { return new DefaultThreadFactory(getClass(), Thread.MAX_PRIORITY); } @Override public EventLoop next() { return (EventLoop) super.next(); } @Override protected abstract EventLoop newChild(Executor executor, Object... args) throws Exception; }
MultithreadEventExecutorGroup 类
public abstract class MultithreadEventExecutorGroup extends AbstractEventExecutorGroup { //接受到任务,交给children 执行 private final EventExecutor[] children; private final Set<EventExecutor> readonlyChildren; private final AtomicInteger childIndex = new AtomicInteger(); private final AtomicInteger terminatedChildren = new AtomicInteger(); private final Promise<?> terminationFuture = new DefaultPromise(GlobalEventExecutor.INSTANCE); /** * Create a new instance. * * @param nThreads the number of threads that will be used by this instance. * @param threadFactory the ThreadFactory to use, or {@code null} if the default should be used. * @param args arguments which will passed to each {@link #newChild(Executor, Object...)} call */ protected MultithreadEventExecutorGroup(int nThreads, ThreadFactory threadFactory, Object... args) { this(nThreads, threadFactory == null ? null : new ThreadPerTaskExecutor(threadFactory), args); } /** * Create a new instance. * * @param nThreads the number of threads that will be used by this instance. * @param executor the Executor to use, or {@code null} if the default should be used. * @param args arguments which will passed to each {@link #newChild(Executor, Object...)} call */ protected MultithreadEventExecutorGroup(int nThreads, Executor executor, Object... args) { if (nThreads <= 0) { throw new IllegalArgumentException(String.format("nThreads: %d (expected: > 0)", nThreads)); } if (executor == null) { executor = new ThreadPerTaskExecutor(newDefaultThreadFactory()); } children = new EventExecutor[nThreads]; for (int i = 0; i < nThreads; i ++) { boolean success = false; try { children[i] = newChild(executor, args); success = true; } catch (Exception e) { // TODO: Think about if this is a good exception type throw new IllegalStateException("failed to create a child event loop", e); } finally { if (!success) { for (int j = 0; j < i; j ++) { children[j].shutdownGracefully(); } for (int j = 0; j < i; j ++) { EventExecutor e = children[j]; try { while (!e.isTerminated()) { e.awaitTermination(Integer.MAX_VALUE, TimeUnit.SECONDS); } } catch (InterruptedException interrupted) { Thread.currentThread().interrupt(); break; } } } } } final FutureListener<Object> terminationListener = new FutureListener<Object>() { @Override public void operationComplete(Future<Object> future) throws Exception { if (terminatedChildren.incrementAndGet() == children.length) { terminationFuture.setSuccess(null); } } }; for (EventExecutor e: children) { e.terminationFuture().addListener(terminationListener); } Set<EventExecutor> childrenSet = new LinkedHashSet<EventExecutor>(children.length); Collections.addAll(childrenSet, children); readonlyChildren = Collections.unmodifiableSet(childrenSet); } protected ThreadFactory newDefaultThreadFactory() { return new DefaultThreadFactory(getClass()); } @Override public EventExecutor next() { return children[Math.abs(childIndex.getAndIncrement() % children.length)]; } ...
We can see the construction method is to create more child (executor real process). Which newChild to the sub-class implementation, we look at the implementation of NioEventLoopGroup newChild.
@Override protected EventLoop newChild(Executor executor, Object... args) throws Exception { return new NioEventLoop(this, executor, (SelectorProvider) args[0]); }
At this point, we find out the final "work" who is NioEventLoop.
Reference material
no