EventLoopGroup
用过Netty的都知道,EventLoopGroup包含多个EventLoop,而一个EventLoop和一个线程绑定,一个Channel绑定到一个EventLoop上,一个EventLoop可以管理多个Channel
EventLoop用来处理Channel的io事件
类继承结构
EventExecutorGroup
EventExecutorGroup主要提供next方法来获取EventExecutor,除此之外可以用来管理EventExecutor的生命周期以及关闭它们
可以看到除了继承的接口的方法,主要提供了一个next方法
EventExecutor
EventExecutor是特殊的EventExecutorGroup,主要提供了一些简便的方法来判断一个线程是否在一个event loop中执行
public interface EventExecutor extends EventExecutorGroup {
/**
* Returns a reference to itself.
*/
@Override
EventExecutor next();
/**
* Return the {@link EventExecutorGroup} which is the parent of this {@link EventExecutor},
*/
EventExecutorGroup parent();
/**
* Calls {@link #inEventLoop(Thread)} with {@link Thread#currentThread()} as argument
*/
boolean inEventLoop();
/**
* Return {@code true} if the given {@link Thread} is executed in the event loop,
* {@code false} otherwise.
*/
boolean inEventLoop(Thread thread);
/**
* Return a new {@link Promise}.
*/
<V> Promise<V> newPromise();
/**
* Create a new {@link ProgressivePromise}.
*/
<V> ProgressivePromise<V> newProgressivePromise();
/**
* Create a new {@link Future} which is marked as successes already. So {@link Future#isSuccess()}
* will return {@code true}. All {@link FutureListener} added to it will be notified directly. Also
* every call of blocking methods will just return without blocking.
*/
<V> Future<V> newSucceededFuture(V result);
/**
* Create a new {@link Future} which is marked as fakued already. So {@link Future#isSuccess()}
* will return {@code false}. All {@link FutureListener} added to it will be notified directly. Also
* every call of blocking methods will just return without blocking.
*/
<V> Future<V> newFailedFuture(Throwable cause);
}
EventLoopGroup
EventLoopGroup是特殊的EventExecutorGroup,主要添加了注册Channel的能力
public interface EventLoopGroup extends EventExecutorGroup {
/**
* Return the next {@link EventLoop} to use
*/
@Override
EventLoop next();
/**
* Register a {@link Channel} with this {@link EventLoop}. The returned {@link ChannelFuture}
* will get notified once the registration was complete.
*/
ChannelFuture register(Channel channel);
/**
* Register a {@link Channel} with this {@link EventLoop}. The passed {@link ChannelFuture}
* will get notified once the registration was complete and also will get returned.
*/
ChannelFuture register(Channel channel, ChannelPromise promise);
}
EventLoop
用来处理注册到EventLoopGroup的channel的所有io事件
public interface EventLoop extends EventExecutor, EventLoopGroup {
@Override
EventLoopGroup parent();
}
AbstractEventExecutorGroup
可以简单地看下其中的几个方法
public abstract class AbstractEventExecutorGroup implements EventExecutorGroup {
@Override
public Future<?> submit(Runnable task) {
return next().submit(task);
}
@Override
public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
return next().schedule(command, delay, unit);
}
@Override
public <T> List<java.util.concurrent.Future<T>> invokeAll(
Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException {
return next().invokeAll(tasks, timeout, unit);
}
}
可以看到submit schedule invokeAll等方法都是将请求透传给next方法返回的对象
NioEventLoopGroup
下面沿着NioEventLoopGroup的继承路径来从上到下看下NioEventLoopGroup的父类
MultithreadEventExecutorGroup
EventExecutorGroup的实现,使用多个线程来执行任务
构造方法
protected MultithreadEventExecutorGroup(int nThreads, ThreadFactory threadFactory, Object... args) {
if (nThreads <= 0) {
throw new IllegalArgumentException(String.format("nThreads: %d (expected: > 0)", nThreads));
}
// 创建线程工厂DefaultThreadFactory
if (threadFactory == null) {
threadFactory = newDefaultThreadFactory();
}
// 创建eventExecutor数组
children = new SingleThreadEventExecutor[nThreads];
// 创建指定个数的eventExecutor
for (int i = 0; i < nThreads; i ++) {
boolean success = false;
try {
// 通过线程工厂和参数来创建一个eventExecutor
// 具体如何创建由子类来实现
children[i] = newChild(threadFactory, 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 {
// 其中一个eventExecutor创建失败
if (!success) {
// 优雅停止之前创建的eventExecutor
for (int j = 0; j < i; j ++) {
children[j].shutdownGracefully();
}
// 等待eventExecutor停止
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;
}
}
}
}
}
// 创建eventExecutor停止回调监听器
final FutureListener<Object> terminationListener = new FutureListener<Object>() {
@Override
public void operationComplete(Future<Object> future) throws Exception {
if (terminatedChildren.incrementAndGet() == children.length) {
terminationFuture.setSuccess(null);
}
}
};
// 每个eventExecutor添加停止回调监听器
for (EventExecutor e: children) {
e.terminationFuture().addListener(terminationListener);
}
}
next
public EventExecutor next() {
// 通过round robin的方式来获取下一个eventExecutor
return children[Math.abs(childIndex.getAndIncrement() % children.length)];
}
MultithreadEventLoopGroup
EventLoopGroup的一个实现,使用多个线程来处理任务
构造方法
static {
// 确定线程的数量
// 如果指定了io.netty.eventLoopThreads,那么使用其作为线程的个数
// 否则使用当前机器的处理器个数*2作为线程的个数
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, ThreadFactory, Object...)}
*/
protected MultithreadEventLoopGroup(int nThreads, ThreadFactory threadFactory, Object... args) {
super(nThreads == 0? DEFAULT_EVENT_LOOP_THREADS : nThreads, threadFactory, args);
}
register
@Override
public ChannelFuture register(Channel channel) {
return next().register(channel);
}
@Override
public ChannelFuture register(Channel channel, ChannelPromise promise) {
return next().register(channel, promise);
}
next
@Override
public EventLoop next() {
return (EventLoop) super.next();
}
NioEventLoopGroup
是MultithreadEventLoopGroup的一个实现类,适用于基于NIO selector的channel
构造方法
从构造方法的入参可以看出,主要需要指定需要使用多少个线程
public NioEventLoopGroup() {
this(0);
}
/**
* Create a new instance using the specified number of threads, {@link ThreadFactory} and the
* {@link SelectorProvider} which is returned by {@link SelectorProvider#provider()}.
*/
public NioEventLoopGroup(int nThreads) {
this(nThreads, null);
}
/**
* Create a new instance using the specified number of threads, the given {@link ThreadFactory} and the
* {@link SelectorProvider} which is returned by {@link SelectorProvider#provider()}.
*/
public NioEventLoopGroup(int nThreads, ThreadFactory threadFactory) {
this(nThreads, threadFactory, SelectorProvider.provider());
}
/**
* Create a new instance using the specified number of threads, the given {@link ThreadFactory} and the given
* {@link SelectorProvider}.
*/
public NioEventLoopGroup(
int nThreads, ThreadFactory threadFactory, final SelectorProvider selectorProvider) {
super(nThreads, threadFactory, selectorProvider);
}
newChild
这里创建的EventExecutor是NioEventLoop类型的
@Override
protected EventExecutor newChild(
ThreadFactory threadFactory, Object... args) throws Exception {
return new NioEventLoop(this, threadFactory, (SelectorProvider) args[0]);
}
OioEventLoopGroup
下面沿着OioEventLoopGroup的继承路径从上到下看下OioEventLoopGroup的父类
ThreadPerChannelEventLoopGroup
为每个注册的channel都新建一个EventLoop
只有在注册channel的时候才会创建EventLoop
构造方法
protected ThreadPerChannelEventLoopGroup(int maxChannels, ThreadFactory threadFactory, Object... args) {
// maxChannel代表当前EventLoopGroup能够处理的channel的最大数量
if (maxChannels < 0) {
throw new IllegalArgumentException(String.format(
"maxChannels: %d (expected: >= 0)", maxChannels));
}
if (threadFactory == null) {
throw new NullPointerException("threadFactory");
}
if (args == null) {
childArgs = EmptyArrays.EMPTY_OBJECTS;
} else {
childArgs = args.clone();
}
this.maxChannels = maxChannels;
this.threadFactory = threadFactory;
tooManyChannels = new ChannelException("too many channels (max: " + maxChannels + ')');
tooManyChannels.setStackTrace(EmptyArrays.EMPTY_STACK_TRACE);
}
next
public EventLoop next() {
throw new UnsupportedOperationException();
}
register
public ChannelFuture register(Channel channel) {
if (channel == null) {
throw new NullPointerException("channel");
}
try {
// 获取一个EventLoop,将当前的channel注册上去
return nextChild().register(channel);
} catch (Throwable t) {
return channel.newFailedFuture(t);
}
}
private EventLoop nextChild() throws Exception {
if (shuttingDown) {
throw new RejectedExecutionException("shutting down");
}
// 首先尝试复用空闲的eventLoop
ThreadPerChannelEventLoop loop = idleChildren.poll();
if (loop == null) {
// 如果没有空闲的eventLoop
// 判断当前正在处理的channel数量是否超过上限,如果超过上限会抛出异常
if (maxChannels > 0 && activeChildren.size() >= maxChannels) {
throw tooManyChannels;
}
// 创建一个新的eventLoop
loop = newChild(childArgs);
loop.terminationFuture().addListener(childTerminationListener);
}
// 将新创建的eventLoop放入到activeChildren这个集合中
activeChildren.add(loop);
return loop;
}
protected ThreadPerChannelEventLoop newChild(
@SuppressWarnings("UnusedParameters") Object... args) throws Exception {
return new ThreadPerChannelEventLoop(this);
}
OioEventLoopGroup
构造方法
可以看到构造方法主要指定的就是最多注册的channle个数
public OioEventLoopGroup() {
this(0);
}
/**
* Create a new {@link OioEventLoopGroup}.
*
* @param maxChannels the maximum number of channels to handle with this instance. Once you try to register
* a new {@link Channel} and the maximum is exceed it will throw an
* {@link ChannelException} on the {@link #register(Channel)} and
* {@link #register(Channel, ChannelPromise)} method.
* Use {@code 0} to use no limit
*/
public OioEventLoopGroup(int maxChannels) {
this(maxChannels, Executors.defaultThreadFactory());
}
/**
* Create a new {@link OioEventLoopGroup}.
*
* @param maxChannels the maximum number of channels to handle with this instance. Once you try to register
* a new {@link Channel} and the maximum is exceed it will throw an
* {@link ChannelException} on the {@link #register(Channel)} and
* {@link #register(Channel, ChannelPromise)} method.
* Use {@code 0} to use no limit
* @param threadFactory the {@link ThreadFactory} used to create new {@link Thread} instances that handle the
* registered {@link Channel}s
*/
public OioEventLoopGroup(int maxChannels, ThreadFactory threadFactory) {
super(maxChannels, threadFactory);
}