本文基于Netty4.x版本
一. 从New一个对象开始
1.NioEventLoopGroup构造
NioEventLoopGroup parentGroup = new NioEventLoopGroup();
密密麻麻的构造函数,挑一个最全的构造
public NioEventLoopGroup(int nThreads, Executor executor, EventExecutorChooserFactory chooserFactory,
final SelectorProvider selectorProvider,
final SelectStrategyFactory selectStrategyFactory,
final RejectedExecutionHandler rejectedExecutionHandler) {
super(nThreads, executor, chooserFactory, selectorProvider, selectStrategyFactory, rejectedExecutionHandler);
}
虽然new NioEventLoopGroup()操作很简洁,但是根据上面最全的构造看出,传递了很多参数。
其中默认参数如下:
- nThreads: 线程数默认0 ,父类MultithreadEventLoopGroup将调整为NettyRuntime.availableProcessors() * 2
- executor: 线程池默认null,父类MultithreadEventExecutorGroup设置为 new ThreadPerTaskExecutor(newDefaultThreadFactory());
- SelectorProvider: selector选择器提供服务,不同系统实现不同
- SelectStrategyFactory: 选择策略工厂
- RejectedExecutionHandler: 拒绝执行处理器
2.MultithreadEventLoopGroup构造
紧接着super调用父类的MultithreadEventLoopGroup构造,先执行静态代码块。
static {
// 设置默认线程数,如果未设置系统参数,则取可利用内核数*2;
DEFAULT_EVENT_LOOP_THREADS = Math.max(1, SystemPropertyUtil.getInt(
"io.netty.eventLoopThreads", NettyRuntime.availableProcessors() * 2));
}
这里的只做了一件事,就是设置DEFAULT_EVENT_LOOP_THREADS 参数。
如果默认传递线程数为0,设置线程数为DEFAULT_EVENT_LOOP_THREADS数值
protected MultithreadEventLoopGroup(int nThreads, Executor executor, Object... args) {
super(nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads, executor, args);
}
3.MultithreadEventExecutorGroup构造
沿着调用链,继续调用父类MultithreadEventExecutorGroup的构造,
途中设置了EventExecutorChooserFactory为DefaultEventExecutorChooserFactory.INSTANCE
protected MultithreadEventExecutorGroup(int nThreads, Executor executor,
EventExecutorChooserFactory chooserFactory, Object... args) {
// 省略线程数校验
...
// 默认这里executor为null
if (executor == null) {
// ThreadPerTaskExecutor是一个特殊线程池,启动一个任务,线程工厂则开启一个新线程
// 这里使用FastThreadLocalThread进行包裹,这是一个优化点
executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
}
children = new EventExecutor[nThreads];
for (int i = 0; i < nThreads; i ++) {
boolean success = false;
try {
// 实例每个NioEventLoop
children[i] = newChild(executor, args);
success = true;
} catch (Exception e) {
...
} finally {
// 进行回滚操作,某个实例化异常,关闭已经启动成功的
...
}
}
// NioEventLoop选择器
chooser = chooserFactory.newChooser(children);
// 设置事件完成监听器
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);
}
二. EventExecutorChooserFactory
public final class DefaultEventExecutorChooserFactory implements EventExecutorChooserFactory {
public EventExecutorChooser newChooser(EventExecutor[] executors) {
// 根据线程数是否为2的幂次方
if (isPowerOfTwo(executors.length)) {
return new PowerOfTwoEventExecutorChooser(executors);
} else {
return new GenericEventExecutorChooser(executors);
}
}
// 判断是否为2的幂
// 已8为例,原码二进制为 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1000
// -8在java中以二进制是补码形式(原码,转为反码,再转为补码;反码为补码除符号为除反码,补码在反码基础上+1)
// -8原码: 1000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1000
// -8反码: 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0111
// -8补码: 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000
// 则 8 & -8 结果还是 8;
private static boolean isPowerOfTwo(int val) {
return (val & -val) == val;
}
private static final class PowerOfTwoEventExecutorChooser implements EventExecutorChooser {
public EventExecutor next() {
return executors[idx.getAndIncrement() & executors.length - 1];
}
}
private static final class GenericEventExecutorChooser implements EventExecutorChooser {
public EventExecutor next() {
return executors[Math.abs(idx.getAndIncrement() % executors.length)];
}
}
}
这里不管实际化哪个对象,执行next都是取余操作。
但为何要区分?
主要是位操作效率更高,毕竟计算机底层还是二进制。
三.NioEventLoop
newChild调用的是子类NioEventLoopGroup的newChild方法
protected EventLoop newChild(Executor executor, Object... args) throws Exception {
return new NioEventLoop(this, executor, (SelectorProvider) args[0],
((SelectStrategyFactory) args[1]).newSelectStrategy(), (RejectedExecutionHandler) args[2]);
}
可以看到newChild是将之前设置的参数,都传入了NioEventLoop。
NioEventLoop(NioEventLoopGroup parent, Executor executor, SelectorProvider selectorProvider,
SelectStrategy strategy, RejectedExecutionHandler rejectedExecutionHandler) {
// 父类方法主要设置参数,建立堵塞队列
super(parent, executor, false, DEFAULT_MAX_PENDING_TASKS, rejectedExecutionHandler);
// 忽略校验逻辑
...
provider = selectorProvider;
// 这里是一个优化点
final SelectorTuple selectorTuple = openSelector();
// 包装过得选择器
selector = selectorTuple.selector;
// 原始的选择器
unwrappedSelector = selectorTuple.unwrappedSelector;
selectStrategy = strategy;
}
跳过NioEventLoop构造中设置参数的操作,主要看下openSelector。
private SelectorTuple openSelector() {
final Selector unwrappedSelector;
try {
// 获取原生的selector,
unwrappedSelector = provider.openSelector();
} catch (IOException e) {W
throw new ChannelException("failed to open a new selector", e);
}
// 是否禁用优化,默认为false
if (DISABLE_KEY_SET_OPTIMIZATION) {
// 返回非优化的对象
return new SelectorTuple(unwrappedSelector);
}
// 获取SelectorImpl的class对象
Object maybeSelectorImplClass = AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
try {
return Class.forName(
"sun.nio.ch.SelectorImpl",
false,
PlatformDependent.getSystemClassLoader());
} catch (Throwable cause) {
return cause;
}
}
});
// 如果获取的SelectorImpl不是类对象或者不是unwrappedSelector的子类
if (!(maybeSelectorImplClass instanceof Class) ||
// ensure the current selector implementation is what we can instrument.
!((Class<?>) maybeSelectorImplClass).isAssignableFrom(unwrappedSelector.getClass())) {
if (maybeSelectorImplClass instanceof Throwable) {
Throwable t = (Throwable) maybeSelectorImplClass;
logger.trace("failed to instrument a special java.util.Set into: {}", unwrappedSelector, t);
}
// 返回非优化的对象
return new SelectorTuple(unwrappedSelector);
}
final Class<?> selectorImplClass = (Class<?>) maybeSelectorImplClass;
final SelectedSelectionKeySet selectedKeySet = new SelectedSelectionKeySet();
Object maybeException = AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
try {
// 反射取值
Field selectedKeysField = selectorImplClass.getDeclaredField("selectedKeys");
Field publicSelectedKeysField = selectorImplClass.getDeclaredField("publicSelectedKeys");
// jdk9+版本
if (PlatformDependent.javaVersion() >= 9 && PlatformDependent.hasUnsafe()) {
long selectedKeysFieldOffset = PlatformDependent.objectFieldOffset(selectedKeysField);
long publicSelectedKeysFieldOffset =
PlatformDependent.objectFieldOffset(publicSelectedKeysField);
if (selectedKeysFieldOffset != -1 && publicSelectedKeysFieldOffset != -1) {
PlatformDependent.putObject(
unwrappedSelector, selectedKeysFieldOffset, selectedKeySet);
PlatformDependent.putObject(
unwrappedSelector, publicSelectedKeysFieldOffset, selectedKeySet);
return null;
}
}
// 设置属性可访问
Throwable cause = ReflectionUtil.trySetAccessible(selectedKeysField, true);
if (cause != null) {
return cause;
}
// 设置属性可访问
cause = ReflectionUtil.trySetAccessible(publicSelectedKeysField, true);
if (cause != null) {
return cause;
}
// 使用SelectedSelectionKeySet替代默认的selectedKeys,publicSelectedKey
// SelectedSelectionKeySet为数组结构,原对象为set结构
selectedKeysField.set(unwrappedSelector, selectedKeySet);
publicSelectedKeysField.set(unwrappedSelector, selectedKeySet);
return null;
} catch (NoSuchFieldException e) {
return e;
} catch (IllegalAccessException e) {
return e;
}
}
});
// 结果异常则,返回未优化的对象
if (maybeException instanceof Exception) {
...
return new SelectorTuple(unwrappedSelector);
}
selectedKeys = selectedKeySet;
return new SelectorTuple(unwrappedSelector,
new SelectedSelectionKeySetSelector(unwrappedSelector, selectedKeySet));
}
这里为何要进行替代默认的属性呢?
主要是数组遍历及新增新元素,效率比map的结构高许多。