2. Executor是JDK中提供的用于分离任务和执行的接口,ExecutorService在Executor基础上增加了一些方法加入了Future, ScheduledExecutorService提供了执行定时任务的方法,
AbstractExecutorService是一个基本实现, AutoClosable提供了close方法接口。
netty4、5的线程模型使得一个Channel上同一时间只会有一个线程进行IO操作,这样使用者便不需要考虑同步并发等多线程问题,大大简化了开发难度。
3. EventExecutorGroup
提供的方法有
shutdownGracefully,netty提供的优雅关闭的方法,通常用于EventLoopGroup的关闭,
重载的shutdownGracefully(long quietPeriod, long timeout, TimeUnit unit),
如果在quietPeriod期间没有任务提交,就关闭,如果有就接受这个任务并重新开始计算quietPeriod,timeout是executor被shutdown后的最大timeout时间,超过这个时间将会关闭。
next() 方法用于获得该EventExecutorGroup管理的下一个EventExecutor
children() 获得该EventExecutorGroup管理的所有子EventExecutor的unmodifiable set集合
4. EventExecutor
inEventLoop() 判断当前线程是否是EventLoop线程
parent() 获得管理它的EventLoopGroup
5. EventLoopGroup
next() 获得下一个EventLoop
register(Channel, ChannelPromise) 在管理的EventLoop集合中选择一个来注册该Channel, 传入的ChannelPromise参数是一个可写的Future,该方法返回的ChannelFuture即为该ChannelPromise
6. EventLoop
unwrap() 用来返回一个不是WrappedEventExecutor的EventLoop,WrappedEventExecutor是一个Marker Interface
asInvoker() 创建一个使用当前EventLoop来进行EventLoop处理的ChannelHandlerInvoker实现,
ChannelHandlerInvoker接口如下,包含了常用的IO触发方法
7 AbstractEventExecutorGroup 中实现了基本的方法,基本上都delegate给next()去执行, next留给了子类去实现。
8 MultithreadEventExecutorGroup 提供了多线程的EventExecutorGroup实现,其内部使用EventExecutor数组保存持有的children, next()方法根据
构造器传入的nEventExecutors判断使用的选择算法选择。
构造器的代码片段。
private MultithreadEventExecutorGroup(int nEventExecutors, Executor executor, boolean shutdownExecutor, Object... args) { if (nEventExecutors <= 0) { throw new IllegalArgumentException( String.format("nEventExecutors: %d (expected: > 0)", nEventExecutors)); } if (executor == null) { executor = newDefaultExecutorService(nEventExecutors); shutdownExecutor = true; } children = new EventExecutor[nEventExecutors]; if (isPowerOfTwo(children.length)) { chooser = new PowerOfTwoEventExecutorChooser(); } else { chooser = new GenericEventExecutorChooser(); } for (int i = 0; i < nEventExecutors; 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) { // Let the caller handle the interruption. Thread.currentThread().interrupt(); break; } } } } } final boolean shutdownExecutor0 = shutdownExecutor; final Executor executor0 = executor; final FutureListener |
9. MultithreadEventLoopGroup继承自MultithreadEventExecutorGroup,提供了默认的EventLoopThread数量的设置,默认为Runtime.availableProcessor() * 2
还有一些覆盖的方法
10. AbstractEventExecutor 继承自AbstractExecutorService, 提供了基本的方法实现。
11. AbstractScheduledEventExecutor 用来支持Schedule, 内部持有Queue
其中关键的代码部分是schedule
|
判断如果当前线程是IO线程,则直接加到任务队列中,否则以Task的形式加入到队列中
11. NioEventLoop
于JDK nio 包相关的实现基本都在这里
持有
Selector selector; private SelectedSelectionKeySet selectedKeys; private final SelectorProvider provider;
selectorAutoRebuildThreshold用于设置JDK Epoll空轮询导致CPU占用100%的bug检测,检测到后重新创建 Selector并将之前的SelectionKey注册到新的Selector上.
@Override protected QueuenewTaskQueue() { // This event loop never calls takeTask() return PlatformDependent.newMpscQueue(); }
返回一个Multi Producer Single Consume 的多生产者单一消费者的队列
注册SelectableChannel的代码
public void register(final SelectableChannel ch, final int interestOps, final NioTask> task) { // some param check try { ch.register(selector, interestOps, task); } catch (Exception e) { throw new EventLoopException("failed to register a channel", e); } } |
RebuildSelector的实现
public void rebuildSelector() { if (!inEventLoop()) { execute(new Runnable() { @Override public void run() { rebuildSelector(); } }); return; } final Selector oldSelector = selector; final Selector newSelector; if (oldSelector == null) { return; } try { newSelector = openSelector(); } catch (Exception e) { logger.warn("Failed to create a new Selector.", e); return; } // Register all channels to the new Selector. int nChannels = 0; for (;;) { try { for (SelectionKey key: oldSelector.keys()) { Object a = key.attachment(); try { if (!key.isValid() || key.channel().keyFor(newSelector) != null) { continue; } int interestOps = key.interestOps(); key.cancel(); SelectionKey newKey = key.channel().register(newSelector, interestOps, a); if (a instanceof AbstractNioChannel) { // Update SelectionKey ((AbstractNioChannel) a).selectionKey = newKey; } nChannels ++; } catch (Exception e) { logger.warn("Failed to re-register a Channel to the new Selector.", e); if (a instanceof AbstractNioChannel) { AbstractNioChannel ch = (AbstractNioChannel) a; ch.unsafe().close(ch.unsafe().voidPromise()); } else { @SuppressWarnings("unchecked") NioTask |
processSelectedKeysPlain
private void processSelectedKeysPlain(Set |