- 浏览: 950380 次
文章分类
- 全部博客 (428)
- Hadoop (2)
- HBase (1)
- ELK (1)
- ActiveMQ (13)
- Kafka (5)
- Redis (14)
- Dubbo (1)
- Memcached (5)
- Netty (56)
- Mina (34)
- NIO (51)
- JUC (53)
- Spring (13)
- Mybatis (17)
- MySQL (21)
- JDBC (12)
- C3P0 (5)
- Tomcat (13)
- SLF4J-log4j (9)
- P6Spy (4)
- Quartz (12)
- Zabbix (7)
- JAVA (9)
- Linux (15)
- HTML (9)
- Lucene (0)
- JS (2)
- WebService (1)
- Maven (4)
- Oracle&MSSQL (14)
- iText (11)
- Development Tools (8)
- UTILS (4)
- LIFE (8)
最新评论
-
Donald_Draper:
Donald_Draper 写道刘落落cici 写道能给我发一 ...
DatagramChannelImpl 解析三(多播) -
Donald_Draper:
刘落落cici 写道能给我发一份这个类的源码吗Datagram ...
DatagramChannelImpl 解析三(多播) -
lyfyouyun:
请问楼主,执行消息发送的时候,报错:Transport sch ...
ActiveMQ连接工厂、连接详解 -
ezlhq:
关于 PollArrayWrapper 状态含义猜测:参考 S ...
WindowsSelectorImpl解析一(FdMap,PollArrayWrapper) -
flyfeifei66:
打算使用xmemcache作为memcache的客户端,由于x ...
Memcached分布式客户端(Xmemcached)
netty 事件执行器组和事件执行器定义及抽象实现:http://donald-draper.iteye.com/blog/2391257
netty 多线程事件执行器组:http://donald-draper.iteye.com/blog/2391270
netty 多线程事件循环组:http://donald-draper.iteye.com/blog/2391276
netty 抽象调度事件执行器:http://donald-draper.iteye.com/blog/2391379
netty 单线程事件执行器初始化:http://donald-draper.iteye.com/blog/2391895
netty 单线程事件执行器执行任务与graceful方式关闭:http://donald-draper.iteye.com/blog/2392051
netty 单线程事件循环:http://donald-draper.iteye.com/blog/2392067
引言:
前面一篇文章我们看了单线程事件循环,来简单回顾一下:
单线程事件循环SingleThreadEventLoop,继承了单线程事件执行器,实现了事件循环接口,内部一个事件循环任务队列,我们可以把单线程事件循环看为一个简单的事件执行器,单线程事件循环中多了一个通道注册的方法,实际注册工作委托给通道关联的UnSafe。
今天我们来看一下Nio事件循环:
来看一下Nio事件循环中,变量的类型声明:
//IntSupplier
再来看Nio事件循环内部实现:
再来关注一下选择Now操作:
再来看选择策略:
从上面可以看出,Nio事件循环内部有一个取消选择key计数器清理间隔CLEANUP_INTERVAL,用于当取消的选择key达到256个时,重置取消选择key计数器cancelledKeys(int),并重新进行选择操作;选择器自动重构阈值SELECTOR_AUTO_REBUILD_THRESHOLD,默认选择操作发生512次,用于控制当选择器发生多少次选择操作时,重构选择器;选择器状态判断器selectNowSupplier,用于获取Nio事件循环内部选择器的选择操作结果;同时有一个选择器selector,未包装过的选择器unwrappedSelector和一个选择器提供者provider,一个选择key就绪集合selectedKeys(SelectedSelectionKeySet);当选择器的选择操作阻塞时,wakenUp(AtomicBoolean)属性决定是否应该break选择操作过程;一个Nio处理Io事件的时间占比ioRatio(int),默认为50,即IO事件处理时间和其他事件处理时间各占Nio事件循环一半;一个选择策略selectStrategy用于控制选择循环,如果返回结果为-1,则下一步应该阻塞选择操作,如果返回结果为-2,则下一步应该调回IO事件循环,处理IO事件,而不是继续执行选择操作,返回值大于0,表示需要有工作要做,即注册到选择器的选择通道有IO事件就绪。
回到Nio事件循环构造:
先看一下选择器元组SelectorTuple的定义:
选择器元组SelectorTuple实际为选择器和未包装选择器的包装类
再来看打开选择器:
再来看选择器包装类
//SelectedSelectionKeySetSelector
选择器包装类的每次选择操作,首先重置就绪选择key集合,再讲相应的操作委托给内部选择器代理,其他打开唤醒等方法直接委托给内部选择器代理。
从上面可以看出,打开选择器,主要是委托给选择器提供者,如果需要优化选择器的,
在当前线程访问控制选择下,加载选择器实现类,不初始化,如果从系统类加载器加载的选择key实现类不是Class实例,或不是裸选择器类型,不进行选择器key集合优化,及选择器为选择器提供者打开的裸选择器;否则在当前线程相同访问控制权限下,获取系统选择器实现类的,选择器就绪key集合selectedKeysField及其代理publicSelectedKeysField,设置选择器就绪key集合selectedKeysField及其代理publicSelectedKeysField访问控制权限,将系统选择器的就绪key集合selectedKeysField及其代理publicSelectedKeysField设值为
selectedKeySet(SelectedSelectionKeySet),并将选择器selector包装为SelectedSelectionKeySetSelector。
Nio事件循环初始化,主要是将Nio事件循环组和事件执行器及任务拒绝策略传给父类,同时打开一个选择器。
总结:
Nio事件循环内部有一个取消选择key计数器清理间隔CLEANUP_INTERVAL,用于当取消的选择key达到256个时,重置取消选择key计数器cancelledKeys(int),并重新进行选择操作;选择器自动重构阈值SELECTOR_AUTO_REBUILD_THRESHOLD,默认选择操作发生512次,用于控制当选择器发生多少次选择操作时,重构选择器;选择器状态判断器selectNowSupplier,用于获取Nio事件循环内部选择器的选择操作结果;同时有一个选择器selector,未包装过的选择器unwrappedSelector和一个选择器提供者provider,一个选择key就绪集合selectedKeys(SelectedSelectionKeySet);当选择器的选择操作阻塞时,wakenUp(AtomicBoolean)属性决定是否应该break选择操作过程;一个Nio处理Io事件的时间占比ioRatio(int),默认为50,即IO事件处理时间和其他事件处理时间各占Nio事件循环一半;一个选择策略selectStrategy用于控制选择循环,如果返回结果为-1,则下一步应该阻塞选择操作,如果返回结果为-2,则下一步应该调回IO事件循环,处理IO事件,而不是继续执行选择操作,返回值大于0,表示需要有工作要做,即注册到选择器的选择通道有IO事件就绪。
Nio事件循环初始化,主要是将Nio事件循环组和事件执行器及任务拒绝策略传给父类单线程事件循环(单线程事件执行器),同时打开一个选择器。
打开选择器过程,委托给选择器提供者打开一个选择器,如果需要优化选择器的,在当前线程访问控制选择下,加载选择器实现类,不初始化,如果从系统类加载器加载的选择key实现类不是Class实例,或不是裸选择器类型,不进行选择器key集合优化,及选择器为选择器提供者打开的裸选择器;否则在当前线程相同访问控制权限下,获取系统选择器实现类的,选择器就绪key集合selectedKeysField及其代理publicSelectedKeysField,设置选择器就绪key集合selectedKeysField及其代理publicSelectedKeysField访问控制权限,将系统选择器的就绪key集合selectedKeysField及其代理publicSelectedKeysField设值为
selectedKeySet(SelectedSelectionKeySet),并将选择器selector包装为SelectedSelectionKeySetSelector。
附:
下面的选择key集合和反射工具,简单看看就行。
//SelectedSelectionKeySet
//ReflectionUtil
netty 多线程事件执行器组:http://donald-draper.iteye.com/blog/2391270
netty 多线程事件循环组:http://donald-draper.iteye.com/blog/2391276
netty 抽象调度事件执行器:http://donald-draper.iteye.com/blog/2391379
netty 单线程事件执行器初始化:http://donald-draper.iteye.com/blog/2391895
netty 单线程事件执行器执行任务与graceful方式关闭:http://donald-draper.iteye.com/blog/2392051
netty 单线程事件循环:http://donald-draper.iteye.com/blog/2392067
引言:
前面一篇文章我们看了单线程事件循环,来简单回顾一下:
单线程事件循环SingleThreadEventLoop,继承了单线程事件执行器,实现了事件循环接口,内部一个事件循环任务队列,我们可以把单线程事件循环看为一个简单的事件执行器,单线程事件循环中多了一个通道注册的方法,实际注册工作委托给通道关联的UnSafe。
今天我们来看一下Nio事件循环:
package io.netty.channel.nio; import io.netty.channel.Channel; import io.netty.channel.ChannelException; import io.netty.channel.EventLoop; import io.netty.channel.EventLoopException; import io.netty.channel.SelectStrategy; import io.netty.channel.SingleThreadEventLoop; import io.netty.util.IntSupplier; import io.netty.util.concurrent.RejectedExecutionHandler; import io.netty.util.internal.PlatformDependent; import io.netty.util.internal.ReflectionUtil; import io.netty.util.internal.SystemPropertyUtil; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; import java.io.IOException; import java.lang.reflect.Field; import java.nio.channels.CancelledKeyException; import java.nio.channels.SelectableChannel; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.spi.SelectorProvider; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.Queue; import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; /** * {@link SingleThreadEventLoop} implementation which register the {@link Channel}'s to a * {@link Selector} and so does the multi-plexing of these in the event loop. Nio单线程事件循环,注册关联通道到同一个选择器,以便复用事件循环。 * */ public final class NioEventLoop extends SingleThreadEventLoop { private static final InternalLogger logger = InternalLoggerFactory.getInstance(NioEventLoop.class); //取消选择key计数器,清理间隔,当取消的选择key达到256个时,重置计数器,并重新进行选择操作 private static final int CLEANUP_INTERVAL = 256; // XXX Hard-coded value, but won't need customization. //是否优化选择器key集合,默认为不优化 private static final boolean DISABLE_KEYSET_OPTIMIZATION = SystemPropertyUtil.getBoolean("io.netty.noKeySetOptimization", false); private static final int MIN_PREMATURE_SELECTOR_RETURNS = 3;//最小的选择器重构阈值 private static final int SELECTOR_AUTO_REBUILD_THRESHOLD;//选择器自动重构阈值,默认选择操作发生512次,重构 private final IntSupplier selectNowSupplier = new IntSupplier() { @Override public int get() throws Exception { return selectNow(); } }; //Nio事件循环任务数量Callable private final Callable<Integer> pendingTasksCallable = new Callable<Integer>() { @Override public Integer call() throws Exception { return NioEventLoop.super.pendingTasks(); } }; // Workaround for JDK NIO bug. // // See: // - http://bugs.sun.com/view_bug.do?bug_id=6427854 // - https://github.com/netty/netty/issues/203 static { //获取java的bug等级 final String key = "sun.nio.ch.bugLevel"; final String buglevel = SystemPropertyUtil.get(key); if (buglevel == null) { //如果bug等级为空,则在当前任务线程相同访问控制权限下,设置nio的bug等级为空 try { AccessController.doPrivileged(new PrivilegedAction<Void>() { @Override public Void run() { System.setProperty(key, ""); return null; } }); } catch (final SecurityException e) { logger.debug("Unable to get/set System Property: " + key, e); } } //初始选择器重构阈值 int selectorAutoRebuildThreshold = SystemPropertyUtil.getInt("io.netty.selectorAutoRebuildThreshold", 512); if (selectorAutoRebuildThreshold < MIN_PREMATURE_SELECTOR_RETURNS) { //不需要重构选择器 selectorAutoRebuildThreshold = 0; } SELECTOR_AUTO_REBUILD_THRESHOLD = selectorAutoRebuildThreshold; if (logger.isDebugEnabled()) { logger.debug("-Dio.netty.noKeySetOptimization: {}", DISABLE_KEYSET_OPTIMIZATION); logger.debug("-Dio.netty.selectorAutoRebuildThreshold: {}", SELECTOR_AUTO_REBUILD_THRESHOLD); } } /** * The NIO {@link Selector}. */ private Selector selector;//就绪选择key集合优化后的选择器 private Selector unwrappedSelector;//没有包装过的选择器,即选择器提供者打开的原始选择器 private SelectedSelectionKeySet selectedKeys;//选择key就绪集合 private final SelectorProvider provider;//选择器提供者 /** * Boolean that controls determines if a blocked Selector.select should * break out of its selection process. In our case we use a timeout for * the select method and the select method will block for that time unless * waken up. 当选择器的选择操作阻塞时,wakenUp属性决定是否应该break选择操作过程。在我们的实现中, 我们给选择操作一个超时时间, 除非选择操作被wakeup,否则选择操作达到超时时间,则break选择操作。 */ private final AtomicBoolean wakenUp = new AtomicBoolean(); private final SelectStrategy selectStrategy;//选择策略 private volatile int ioRatio = 50;//Nio处理Io事件的时间占比,以便可以处理器其他非IO事件 private int cancelledKeys;//取消选择key计数器 private boolean needsToSelectAgain;//是否需要重新选择 }
来看一下Nio事件循环中,变量的类型声明:
//IntSupplier
package io.netty.util; /** * Represents a supplier of {@code int}-valued results. 表示一个int值供应者 */ public interface IntSupplier { /** * Gets a result. * * @return a result */ int get() throws Exception; }
再来看Nio事件循环内部实现:
private final IntSupplier selectNowSupplier = new IntSupplier() { //获取选择操作返回值,用于判断注册到当前选择器的选择通道是否有IO事件就绪 @Override public int get() throws Exception { return selectNow(); } };
再来关注一下选择Now操作:
int selectNow() throws IOException { try { //直接委托个Nio事件循环选择器 return selector.selectNow(); } finally { // restore wakeup state if needed //如果选择操作后,需要唤醒等待选择操作的线程,则唤醒 if (wakenUp.get()) { selector.wakeup(); } } }
再来看选择策略:
private final SelectStrategy selectStrategy;//选择策略
package io.netty.channel; import io.netty.util.IntSupplier; /** * Select strategy interface. * * Provides the ability to control the behavior of the select loop. For example a blocking select * operation can be delayed or skipped entirely if there are events to process immediately. 选择策略接口提供了控制选择循环行为的方法。比如,如果有事件需要立刻处理,则可以阻塞选择操作或 完全直接跳过。 */ public interface SelectStrategy { /** * Indicates a blocking select should follow. 阻塞选择操作 */ int SELECT = -1; /** * Indicates the IO loop should be retried, no blocking select to follow directly. 如果没有选择操作阻塞,预示着应该重试IO事件循环,处理IO事件 */ int CONTINUE = -2; /** * The {@link SelectStrategy} can be used to steer the outcome of a potential select * call. *选择策略可以用于控制潜在的选择操作结果 * @param selectSupplier The supplier with the result of a select result. 选择结果提供者 * @param hasTasks true if tasks are waiting to be processed. 是否有任务待处理 * @return {@link #SELECT} if the next step should be blocking select {@link #CONTINUE} if * the next step should be to not select but rather jump back to the IO loop and try * again. Any value >= 0 is treated as an indicator that work needs to be done. 如果返回结果为-1,则下一步应该阻塞选择操作,如果返回结果为-2,则下一步应该调回IO事件循环,处理 IO事件,而不是继续执行选择操作,返回值大于0,表示需要有工作要做,即注册到选择器的选择通道有IO事件 就绪。 */ int calculateStrategy(IntSupplier selectSupplier, boolean hasTasks) throws Exception; }
从上面可以看出,Nio事件循环内部有一个取消选择key计数器清理间隔CLEANUP_INTERVAL,用于当取消的选择key达到256个时,重置取消选择key计数器cancelledKeys(int),并重新进行选择操作;选择器自动重构阈值SELECTOR_AUTO_REBUILD_THRESHOLD,默认选择操作发生512次,用于控制当选择器发生多少次选择操作时,重构选择器;选择器状态判断器selectNowSupplier,用于获取Nio事件循环内部选择器的选择操作结果;同时有一个选择器selector,未包装过的选择器unwrappedSelector和一个选择器提供者provider,一个选择key就绪集合selectedKeys(SelectedSelectionKeySet);当选择器的选择操作阻塞时,wakenUp(AtomicBoolean)属性决定是否应该break选择操作过程;一个Nio处理Io事件的时间占比ioRatio(int),默认为50,即IO事件处理时间和其他事件处理时间各占Nio事件循环一半;一个选择策略selectStrategy用于控制选择循环,如果返回结果为-1,则下一步应该阻塞选择操作,如果返回结果为-2,则下一步应该调回IO事件循环,处理IO事件,而不是继续执行选择操作,返回值大于0,表示需要有工作要做,即注册到选择器的选择通道有IO事件就绪。
回到Nio事件循环构造:
NioEventLoop(NioEventLoopGroup parent, Executor executor, SelectorProvider selectorProvider, SelectStrategy strategy, RejectedExecutionHandler rejectedExecutionHandler) { super(parent, executor, false, DEFAULT_MAX_PENDING_TASKS, rejectedExecutionHandler); if (selectorProvider == null) { throw new NullPointerException("selectorProvider"); } if (strategy == null) { throw new NullPointerException("selectStrategy"); } provider = selectorProvider; //打开选择器 final SelectorTuple selectorTuple = openSelector(); selector = selectorTuple.selector; unwrappedSelector = selectorTuple.unwrappedSelector; selectStrategy = strategy; }
先看一下选择器元组SelectorTuple的定义:
private static final class SelectorTuple { final Selector unwrappedSelector; final Selector selector; SelectorTuple(Selector unwrappedSelector) { this.unwrappedSelector = unwrappedSelector; this.selector = unwrappedSelector; } SelectorTuple(Selector unwrappedSelector, Selector selector) { this.unwrappedSelector = unwrappedSelector; this.selector = selector; } }
选择器元组SelectorTuple实际为选择器和未包装选择器的包装类
再来看打开选择器:
//打开选择器 final SelectorTuple selectorTuple = openSelector();
private SelectorTuple openSelector() { final Selector unwrappedSelector; try { //从选择器提供者打开一个选择器,刚打开的选择器是未包装的选择器,裸选择器 unwrappedSelector = provider.openSelector(); } catch (IOException e) { throw new ChannelException("failed to open a new selector", e); } //如果key集合不优化,则选择器默认为选择器提供者打开的选择器 if (DISABLE_KEYSET_OPTIMIZATION) { return new SelectorTuple(unwrappedSelector); } //下面是优化选择器集合 final SelectedSelectionKeySet selectedKeySet = new SelectedSelectionKeySet(); //在当前线程访问控制选择下,加载选择器实现类,不初始化 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; } } }); //如果从系统类加载器加载的选择key实现类不是Class实例,或不是裸选择器类型,不进行选择器key集合优化 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; Object maybeException = AccessController.doPrivileged(new PrivilegedAction<Object>() { @Override public Object run() { try { //在当前线程相同访问控制权限下,获取系统选择器实现类的 //选择器就绪key集合selectedKeysField及其代理publicSelectedKeysField Field selectedKeysField = selectorImplClass.getDeclaredField("selectedKeys"); Field publicSelectedKeysField = selectorImplClass.getDeclaredField("publicSelectedKeys"); //设置选择器就绪key集合selectedKeysField及其代理publicSelectedKeysField访问控制权限 Throwable cause = ReflectionUtil.trySetAccessible(selectedKeysField); if (cause != null) { return cause; } cause = ReflectionUtil.trySetAccessible(publicSelectedKeysField); if (cause != null) { return cause; } //将系统选择器的就绪key集合selectedKeysField及其代理publicSelectedKeysField //设置为selectedKeySet selectedKeysField.set(unwrappedSelector, selectedKeySet); publicSelectedKeysField.set(unwrappedSelector, selectedKeySet); return null; } catch (NoSuchFieldException e) { return e; } catch (IllegalAccessException e) { return e; } } }); if (maybeException instanceof Exception) { selectedKeys = null; Exception e = (Exception) maybeException; logger.trace("failed to instrument a special java.util.Set into: {}", unwrappedSelector, e); return new SelectorTuple(unwrappedSelector); } //初始化选择key集合 selectedKeys = selectedKeySet; logger.trace("instrumented a special java.util.Set into: {}", unwrappedSelector); return new SelectorTuple(unwrappedSelector, new SelectedSelectionKeySetSelector(unwrappedSelector, selectedKeySet)); }
再来看选择器包装类
//SelectedSelectionKeySetSelector
package io.netty.channel.nio; import java.io.IOException; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.spi.SelectorProvider; import java.util.Set; final class SelectedSelectionKeySetSelector extends Selector { private final SelectedSelectionKeySet selectionKeys;//就绪的选择key集合 private final Selector delegate;//选择器代理 SelectedSelectionKeySetSelector(Selector delegate, SelectedSelectionKeySet selectionKeys) { this.delegate = delegate; this.selectionKeys = selectionKeys; } @Override public boolean isOpen() { return delegate.isOpen(); } @Override public SelectorProvider provider() { return delegate.provider(); } @Override public Set<SelectionKey> keys() { return delegate.keys(); } @Override public Set<SelectionKey> selectedKeys() { return delegate.selectedKeys(); } //每次选择操作,重置就绪选择key集合 @Override public int selectNow() throws IOException { selectionKeys.reset(); return delegate.selectNow(); } @Override public int select(long timeout) throws IOException { selectionKeys.reset(); return delegate.select(timeout); } @Override public int select() throws IOException { selectionKeys.reset(); return delegate.select(); } @Override public Selector wakeup() { return delegate.wakeup(); } @Override public void close() throws IOException { delegate.close(); } }
选择器包装类的每次选择操作,首先重置就绪选择key集合,再讲相应的操作委托给内部选择器代理,其他打开唤醒等方法直接委托给内部选择器代理。
从上面可以看出,打开选择器,主要是委托给选择器提供者,如果需要优化选择器的,
在当前线程访问控制选择下,加载选择器实现类,不初始化,如果从系统类加载器加载的选择key实现类不是Class实例,或不是裸选择器类型,不进行选择器key集合优化,及选择器为选择器提供者打开的裸选择器;否则在当前线程相同访问控制权限下,获取系统选择器实现类的,选择器就绪key集合selectedKeysField及其代理publicSelectedKeysField,设置选择器就绪key集合selectedKeysField及其代理publicSelectedKeysField访问控制权限,将系统选择器的就绪key集合selectedKeysField及其代理publicSelectedKeysField设值为
selectedKeySet(SelectedSelectionKeySet),并将选择器selector包装为SelectedSelectionKeySetSelector。
Nio事件循环初始化,主要是将Nio事件循环组和事件执行器及任务拒绝策略传给父类,同时打开一个选择器。
总结:
Nio事件循环内部有一个取消选择key计数器清理间隔CLEANUP_INTERVAL,用于当取消的选择key达到256个时,重置取消选择key计数器cancelledKeys(int),并重新进行选择操作;选择器自动重构阈值SELECTOR_AUTO_REBUILD_THRESHOLD,默认选择操作发生512次,用于控制当选择器发生多少次选择操作时,重构选择器;选择器状态判断器selectNowSupplier,用于获取Nio事件循环内部选择器的选择操作结果;同时有一个选择器selector,未包装过的选择器unwrappedSelector和一个选择器提供者provider,一个选择key就绪集合selectedKeys(SelectedSelectionKeySet);当选择器的选择操作阻塞时,wakenUp(AtomicBoolean)属性决定是否应该break选择操作过程;一个Nio处理Io事件的时间占比ioRatio(int),默认为50,即IO事件处理时间和其他事件处理时间各占Nio事件循环一半;一个选择策略selectStrategy用于控制选择循环,如果返回结果为-1,则下一步应该阻塞选择操作,如果返回结果为-2,则下一步应该调回IO事件循环,处理IO事件,而不是继续执行选择操作,返回值大于0,表示需要有工作要做,即注册到选择器的选择通道有IO事件就绪。
Nio事件循环初始化,主要是将Nio事件循环组和事件执行器及任务拒绝策略传给父类单线程事件循环(单线程事件执行器),同时打开一个选择器。
打开选择器过程,委托给选择器提供者打开一个选择器,如果需要优化选择器的,在当前线程访问控制选择下,加载选择器实现类,不初始化,如果从系统类加载器加载的选择key实现类不是Class实例,或不是裸选择器类型,不进行选择器key集合优化,及选择器为选择器提供者打开的裸选择器;否则在当前线程相同访问控制权限下,获取系统选择器实现类的,选择器就绪key集合selectedKeysField及其代理publicSelectedKeysField,设置选择器就绪key集合selectedKeysField及其代理publicSelectedKeysField访问控制权限,将系统选择器的就绪key集合selectedKeysField及其代理publicSelectedKeysField设值为
selectedKeySet(SelectedSelectionKeySet),并将选择器selector包装为SelectedSelectionKeySetSelector。
附:
下面的选择key集合和反射工具,简单看看就行。
//SelectedSelectionKeySet
package io.netty.channel.nio; import java.nio.channels.SelectionKey; import java.util.AbstractSet; import java.util.Arrays; import java.util.Iterator; final class SelectedSelectionKeySet extends AbstractSet<SelectionKey> { SelectionKey[] keys; int size; SelectedSelectionKeySet() { keys = new SelectionKey[1024]; } @Override public boolean add(SelectionKey o) { if (o == null) { return false; } keys[size++] = o; if (size == keys.length) { increaseCapacity(); } return true; } @Override public int size() { return size; } @Override public boolean remove(Object o) { return false; } @Override public boolean contains(Object o) { return false; } @Override public Iterator<SelectionKey> iterator() { throw new UnsupportedOperationException(); } void reset() { reset(0); } void reset(int start) { Arrays.fill(keys, start, size, null); size = 0; } private void increaseCapacity() { SelectionKey[] newKeys = new SelectionKey[keys.length << 1]; System.arraycopy(keys, 0, newKeys, 0, size); keys = newKeys; } }
//ReflectionUtil
package io.netty.util.internal; import java.lang.reflect.AccessibleObject; public final class ReflectionUtil { private ReflectionUtil() { } /** * Try to call {@link AccessibleObject#setAccessible(boolean)} but will catch any {@link SecurityException} and * {@link java.lang.reflect.InaccessibleObjectException} and return it. * The caller must check if it returns {@code null} and if not handle the returned exception. */ public static Throwable trySetAccessible(AccessibleObject object) { try { object.setAccessible(true); return null; } catch (SecurityException e) { return e; } catch (RuntimeException e) { return handleInaccessibleObjectException(e); } } private static RuntimeException handleInaccessibleObjectException(RuntimeException e) { // JDK 9 can throw an inaccessible object exception here; since Netty compiles // against JDK 7 and this exception was only added in JDK 9, we have to weakly // check the type if ("java.lang.reflect.InaccessibleObjectException".equals(e.getClass().getName())) { return e; } throw e; } }
发表评论
-
netty NioSocketChannel解析
2017-09-29 12:50 1230netty 抽象BootStrap定义:http://dona ... -
netty Pooled字节buf分配器
2017-09-28 13:00 1968netty 字节buf定义:http://donald-dra ... -
netty Unpooled字节buf分配器
2017-09-26 22:01 2358netty 字节buf定义:http://donald-dra ... -
netty 抽象字节buf分配器
2017-09-26 08:43 1255netty 字节buf定义:http:// ... -
netty 复合buf概念
2017-09-25 22:31 1252netty 字节buf定义:http://donald-dra ... -
netty 抽象字节buf引用计数器
2017-09-22 12:48 1518netty 字节buf定义:http://donald-dra ... -
netty 抽象字节buf解析
2017-09-22 09:00 1758netty 通道接口定义:http://donald-drap ... -
netty 资源泄漏探测器
2017-09-21 09:37 1322netty 通道接口定义:http://donald-drap ... -
netty 字节buf定义
2017-09-20 08:31 2748netty 通道接口定义:http://donald-drap ... -
netty 默认通道配置后续
2017-09-18 08:36 2094netty 通道接口定义:http://donald-drap ... -
netty 默认通道配置初始化
2017-09-17 22:51 1937netty 通道接口定义:http://donald-drap ... -
netty 通道配置接口定义
2017-09-17 14:51 1011netty 通道接口定义:http://donald-drap ... -
netty NioServerSocketChannel解析
2017-09-16 13:01 1806netty ServerBootStrap解析:http:// ... -
netty 抽象nio消息通道
2017-09-15 15:30 1158netty 通道接口定义:http:/ ... -
netty 抽象nio字节通道
2017-09-14 22:39 1140netty 通道接口定义:http:/ ... -
netty 抽象nio通道解析
2017-09-14 17:23 889netty 通道接口定义:http://donald-drap ... -
netty 抽象通道后续
2017-09-13 22:40 1234netty Inboudn/Outbound通道Inv ... -
netty 通道Outbound缓冲区
2017-09-13 14:31 2123netty 通道接口定义:http:/ ... -
netty 抽象Unsafe定义
2017-09-12 21:24 992netty 通道接口定义:http:/ ... -
netty 抽象通道初始化
2017-09-11 12:56 1788netty 管道线定义-ChannelPipeline:htt ...
相关推荐
netty开发之nio netty开发之nio netty开发之nio netty开发之nio netty开发之nio netty开发之nio netty开发之nio netty开发之nio netty开发之nio netty开发之nio netty开发之nio netty开发之nio netty开发之nio netty...
netty nio 封装java nio用于网络分布式数据传输。
基于netty的nio使用demo源码
包含了Netty,NIO AIO,Mina知识的详解以及netty结合spring protocolbuf的源码
Java高并发编程代码(Netty NIO 实例)
jaca视频教程 jaca游戏服务器端开发 Netty NIO AIO Mina视频教程 课程目录: 一、Netty快速入门教程 01、第一课NIO 02、第二课netty服务端 03、第三课netty客户端 04、第四课netty线程模型源码分析(一) 05、...
资源名称:Java_NIO框架Netty教程资源截图: 资源太大,传百度网盘了,链接在附件中,有需要的同学自取。
myeclipse开发通信示例,框架netty,代码本人写的,而且已测试通过,先运行NettyService,再运行NettyClient即可看到效果。nio示例也有,原理一样,运行先后顺序同netty.
视频分两部分:第一部分:深入浅出Netty源码剖析;第二部分:NIO+Netty5各种RPC架构实战演练(非加密)
Netty01-nio.md
t-io是基于aio(nio2)的网络编程框架,和netty属于同类,但t-io更注重开发一线工程师的感受,提供了大量和业务相关的API。基于t-io来开发IM、TCP私有协议、RPC、游戏服务器端、推送服务、实时监控、物联网、UDP、...
Netty是一个NIO客户端服务器框架,可以快速轻松地开发网络应用程序,例如协议服务器和客户端。它极大地简化和简化了TCP和UDP套接字服务器等网络编程。 “快速简便”并不意味着最终的应用程序将遭受可维护性或性能...
NIO与Netty编程-课程讲义,包含 BIO、NIO、Io的介绍,NIO网络聊天的案列,自定义RPC的实现与设计
java_Netty权威指南,详解nio,tcp,http,netty.rar
用Netty实现NIO Socket聊天系统示例 ,完整代码,已开源,希望大家多提意见。
netty 新NIO框架 文档,在jetty项目中用到了该框架。 netty更注重IO读写,效率很高。更支持servlet1.0异步的websocket。值得一看
【项目实战】Netty源码剖析&NIO;+Netty5各种RPC架构实战演练三部曲视频教程(未加密)
如何全面系统地掌握Netty,进行Netty NIO开发、Netty编解码开发、Netty多协议开发?如何通过对Netty源码的学习获得更深入地知识?掌握了Netty后,如何将其应用到实际架构中?Netty工程师的就业前景和可涉足的行业是怎样...
主要介绍了java基于netty NIO的简单聊天室的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
Java异步NIO框架Netty实现高性能高并发无标题笔记 1. 背景 1.1. 惊人的性能数据 最近一个圈内朋友通过私信告诉我,通过使用Netty4 + Thrift压缩二进制编解码技术,他们实现了10W TPS(1K的复杂POJO对象)的跨 节点...