当前位置: 首页 > news >正文

阳朔到桂林大巴时刻表/整站seo优化公司

阳朔到桂林大巴时刻表,整站seo优化公司,营销网站,青海高端网站建设大纲 1.关于NioEventLoop的问题整理 2.理解Reactor线程模型主要分三部分 3.NioEventLoop的创建 4.NioEventLoop的启动 1.关于NioEventLoop的问题整理 一.默认下Netty服务端起多少线程及何时启动? 答:默认是2倍CPU核数个线程。在调用EventExcutor的…

大纲

1.关于NioEventLoop的问题整理

2.理解Reactor线程模型主要分三部分

3.NioEventLoop的创建

4.NioEventLoop的启动

1.关于NioEventLoop的问题整理

一.默认下Netty服务端起多少线程及何时启动?

答:默认是2倍CPU核数个线程。在调用EventExcutor的execute(task)方法时,会判断当前线程是否为Netty的Reactor线程,也就是判断当前线程是否为NioEventLoop对应的线程实体。如果是,则说明Netty的Reactor线程已经启动了。如果不是,则说明是外部线程调用EventExcutor的execute()方法。于是会先调用startThread()方法判断当前线程是否已被启动,如果还没有被启动就启动当前线程作为Netty的Reactor线程。

二.Netty是如何解决JDK空轮询的?

答:Netty会判断如果当前阻塞的一个Select()操作并没有花那么长时间,那么就说明此时有可能触发了空轮询Bug。默认情况下如果这个现象达到512次,那么就重建一个Selector,并且把之前Selector上所有的key重新移交到新Selector上。通过以上这种处理方式来避免JDK空轮询Bug。

三.Netty是如何保证异步串行无锁化的?

答:异步串行无锁化有两个场景。

场景一:拿到客户端一个Channel,不需要对该Channel进行同步,直接就可以多线程并发读写。

场景二:ChannelHandler里的所有操作都是线程安全的,不需要进行同步。

Netty在所有外部线程去调用EventLoop或者Channel的方法时,会通过inEventLoop()方法来判断出当前线程是外部线程(非NioEventLoop的线程实体)。在这种情况下,会把所有操作都封装成一个Task放入MPSC队列,然后在NioEventLoop的执行逻辑也就是run()方法里,这些Task会被逐个执行。

2.理解Reactor线程模型主要分三部分

一.NioEventLoop的创建

二.NioEventLoop的启动

三.NioEventLoop的执行

3.NioEventLoop的创建

(1)创建入口

(2)确定NioEventLoop的个数

(3)NioEventLoopGroup的创建流程

(4)创建线程执行器ThreadPerTaskExecutor

(5)创建NioEventLoop

(6)创建线程选择器EventExecutorChooser

(7)NioEventLoopGroup的创建总结

(1)创建入口

EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();

(2)确定NioEventLoop的个数

由NioEventLoopGroup的构造方法来确定NioEventLoop的个数。如果NioEventLoopGroup没有传递构造参数,那么NioEventLoop线程的个数为CPU核数的2倍。如果NioEventLoopGroup传递了参数n,那么NioEventLoop线程的个数就是n。

(3)NioEventLoopGroup的创建流程

NioEventLoopGroup的构造方法会触发创建流程。

一.创建线程执行器ThreadPerTaskExecutor

每次调用ThreadPerTaskExecutor.execute()方法时都会创建一个线程。

二.创建NioEventLoop

NioEventLoop对应NioEventLoopGroup线程池里的线程,NioEventLoopGroup的构造方法会用一个for循环通过调用newChild()方法来创建NioEventLoop线程。

三.创建线程选择器EventExecutorChooser

线程选择器的作用是用于给每个新连接分配一个NioEventLoop线程,也就是从NioEventLoopGroup线程池中选择一个NioEventLoop线程来处理新连接。

//MultithreadEventLoopGroup implementations which is used for NIO Selector based Channels.
public class NioEventLoopGroup extends MultithreadEventLoopGroup {//Create a new instance using the default number of threads, //the default ThreadFactory and the SelectorProvider which is returned by SelectorProvider#provider().public NioEventLoopGroup() {this(0);}//Create a new instance using the specified number of threads, //ThreadFactory and the SelectorProvider which is returned by SelectorProvider#provider().public NioEventLoopGroup(int nThreads) {this(nThreads, (Executor) null);}public NioEventLoopGroup(int nThreads, Executor executor) {this(nThreads, executor, SelectorProvider.provider());}public NioEventLoopGroup(int nThreads, Executor executor, final SelectorProvider selectorProvider) {this(nThreads, executor, selectorProvider, DefaultSelectStrategyFactory.INSTANCE);}public NioEventLoopGroup(int nThreads, Executor executor, final SelectorProvider selectorProvider, final SelectStrategyFactory selectStrategyFactory) { super(nThreads, executor, selectorProvider, selectStrategyFactory, RejectedExecutionHandlers.reject());}...
}//Abstract base class for EventLoopGroup implementations that handles their tasks with multiple threads at the same time.
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;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);}protected MultithreadEventLoopGroup(int nThreads, Executor executor, Object... args) {super(nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads, executor, args);}...
}//Abstract base class for EventExecutorGroup implementations that handles their tasks with multiple threads at the same time.
public abstract class MultithreadEventExecutorGroup extends AbstractEventExecutorGroup {private final EventExecutor[] children;private final EventExecutorChooserFactory.EventExecutorChooser chooser;...//Create a new instance.protected MultithreadEventExecutorGroup(int nThreads, Executor executor, Object... args) {this(nThreads, executor, DefaultEventExecutorChooserFactory.INSTANCE, 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 null if the default should be used.//@param chooserFactory,the EventExecutorChooserFactory to use.//@param args,arguments which will passed to each #newChild(Executor, Object...) callprotected MultithreadEventExecutorGroup(int nThreads, Executor executor, EventExecutorChooserFactory chooserFactory, Object... args) {if (nThreads <= 0) throw new IllegalArgumentException(String.format("nThreads: %d (expected: > 0)", nThreads));//1.创建ThreadPerTaskExecutor线程执行器if (executor == null) executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());//2.创建NioEventLoopchildren = new EventExecutor[nThreads];for (int i = 0; i < nThreads; i ++) {...//创建每一个NioEventLoop时,都会调用newChild()方法给每一个NioEventLoop配置一些核心参数//传入线程执行器executor去创建NioEventLoopchildren[i] = newChild(executor, args);}//3.创建线程选择器chooser = chooserFactory.newChooser(children);...}...
}

创建NioEventLoopGroup的脉络如下:

new NioEventLoopGroup() //线程组,线程个数默认为2 * CPU核数new ThreadPerTaskExecutor() //创建线程执行器,作用是负责创建NioEventLoop对应的线程for(...) { newChild() } //构造NioEventLoop,创建NioEventLoop线程组chooserFactory.newChooser() //线程选择器,用于给每个新连接分配一个NioEventLoop线程

(4)创建线程执行器ThreadPerTaskExecutor

ThreadPerTaskExecutor的作用是:每次调用它的execute()方法执行Runnable任务时,都会通过threadFactory.newThread()创建出一个线程,然后把要执行的Runnable任务传递进该线程进行执行。

其中成员变量threadFactory是在传参给ThreadPerTaskExecutor的构造方法时,由newDefaultThreadFactory()方法构建的,也就是一个DefaultThreadFactory对象。

所以线程执行器ThreadPerTaskExecutor在通过threadFactory.newThread()创建线程时,其实就是调用DefaultThreadFactory的newThread()方法。

而DefaultThreadFactory.newThread()方法创建出来的线程实体,是Netty经过优化之后的FastThreadLocalThread对象,这个线程实体在操作ThreadLocal时,要比JDK快。

ThreadPerTaskExecutor线程执行器总结:

一.每次执行ThreadPerTaskExecutor的execute()方法时,都会创建出一个FastThreadLocalThread的线程实体,所以Netty的线程实体都是由ThreadPerTaskExecutor创建的。

二.FastThreadLocalThread线程实体的命名规则是:nioEventLoop-自增的线程池编号-自增的线程数编号。

//Abstract base class for EventExecutorGroup implementations that handles their tasks with multiple threads at the same time.
public abstract class MultithreadEventExecutorGroup extends AbstractEventExecutorGroup {private final EventExecutor[] children;private final EventExecutorChooserFactory.EventExecutorChooser chooser;...    //Create a new instance.protected MultithreadEventExecutorGroup(int nThreads, Executor executor, EventExecutorChooserFactory chooserFactory, Object... args) {if (nThreads <= 0) throw new IllegalArgumentException(String.format("nThreads: %d (expected: > 0)", nThreads));//1.创建ThreadPerTaskExecutor线程执行器if (executor == null) executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());//2.创建NioEventLoopchildren = new EventExecutor[nThreads];for (int i = 0; i < nThreads; i ++) {...//创建每一个NioEventLoop时,都会调用newChild()方法给每一个NioEventLoop配置一些核心参数//传入线程执行器executor去创建NioEventLoopchildren[i] = newChild(executor, args);}//3.创建线程选择器chooser = chooserFactory.newChooser(children);...}protected ThreadFactory newDefaultThreadFactory() {//getClass()是获取该方法所属的对象类型,也就是NioEventLoopGroup类型//因为是通过NioEventLoopGroup的构造方法层层调用到这里的return new DefaultThreadFactory(getClass());}...
}public final class ThreadPerTaskExecutor implements Executor {private final ThreadFactory threadFactory;public ThreadPerTaskExecutor(ThreadFactory threadFactory) {if (threadFactory == null) throw new NullPointerException("threadFactory");this.threadFactory = threadFactory;}@Overridepublic void execute(Runnable command) {//调用DefaultThreadFactory的newThread()方法执行Runnable任务threadFactory.newThread(command).start();}
}//A ThreadFactory implementation with a simple naming rule.
public class DefaultThreadFactory implements ThreadFactory {private static final AtomicInteger poolId = new AtomicInteger();private final AtomicInteger nextId = new AtomicInteger();private final boolean daemon;private final int priority;protected final ThreadGroup threadGroup;...public DefaultThreadFactory(Class<?> poolType) {this(poolType, false, Thread.NORM_PRIORITY);}public DefaultThreadFactory(Class<?> poolType, boolean daemon, int priority) {//toPoolName()方法会把NioEventLoopGroup的首字母变成小写this(toPoolName(poolType), daemon, priority);}public DefaultThreadFactory(String poolName, boolean daemon, int priority) {this(poolName, daemon, priority, System.getSecurityManager() == null? Thread.currentThread().getThreadGroup() : System.getSecurityManager().getThreadGroup());}public DefaultThreadFactory(String poolName, boolean daemon, int priority, ThreadGroup threadGroup) {...//prefix用来标记线程名字的前缀prefix = poolName + '-' + poolId.incrementAndGet() + '-';this.daemon = daemon;this.priority = priority;this.threadGroup = threadGroup;}@Overridepublic Thread newThread(Runnable r) {Thread t = newThread(new DefaultRunnableDecorator(r), prefix + nextId.incrementAndGet());if (t.isDaemon()) {if (!daemon) t.setDaemon(false);} else {if (daemon) t.setDaemon(true);}if (t.getPriority() != priority) t.setPriority(priority);return t;}protected Thread newThread(Runnable r, String name) {return new FastThreadLocalThread(threadGroup, r, name);}...
}

(5)创建NioEventLoop

说明一:

由MultithreadEventExecutorGroup的构造方法可知,Netty会使用for循环 + newChild()方法来创建nThreads个NioEventLoop,而且一个NioEventLoop对应一个线程实体FastThreadLocalThread。

//Abstract base class for EventExecutorGroup implementations that handles their tasks with multiple threads at the same time.
public abstract class MultithreadEventExecutorGroup extends AbstractEventExecutorGroup {private final EventExecutor[] children;private final EventExecutorChooserFactory.EventExecutorChooser chooser;...    //Create a new instance.protected MultithreadEventExecutorGroup(int nThreads, Executor executor, EventExecutorChooserFactory chooserFactory, Object... args) {if (nThreads <= 0) throw new IllegalArgumentException(String.format("nThreads: %d (expected: > 0)", nThreads));//1.创建ThreadPerTaskExecutor线程执行器if (executor == null) executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());//2.创建NioEventLoopchildren = new EventExecutor[nThreads];for (int i = 0; i < nThreads; i ++) {...//创建每一个NioEventLoop时,都会调用newChild()方法给每一个NioEventLoop配置一些核心参数//传入线程执行器executor去创建NioEventLoopchildren[i] = newChild(executor, args);}//3.创建线程选择器chooser = chooserFactory.newChooser(children);...}//Create a new EventExecutor which will later then accessible via the #next() method.//This method will be called for each thread that will serve this MultithreadEventExecutorGroup.protected abstract EventExecutor newChild(Executor executor, Object... args) throws Exception;...
}

说明二:

MultithreadEventExecutorGroup的newChild()抽象方法是由NioEventLoopGroup实现的,所以在执行NioEventLoopGroup的默认构造方法时也会执行其newChild()方法。

NioEventLoopGroup的newChild()方法需要传递一个executor参数,该参数就是执行NioEventLoopGroup构造方法开始时创建的线程执行器,之后newChild()方法会返回一个新创建的NioEventLoop对象。

//MultithreadEventLoopGroup implementations which is used for NIO Selector based Channels.
public class NioEventLoopGroup extends MultithreadEventLoopGroup {...@Overrideprotected EventLoop newChild(Executor executor, Object... args) throws Exception {//executor是执行NioEventLoopGroup构造方法开始时创建的线程执行器ThreadPerTaskExecutor//this指的是NioEventLoopGroup,表示新创建的NioEventLoop对象归属哪个NioEventLoopGroupreturn new NioEventLoop(this, executor, (SelectorProvider) args[0],((SelectStrategyFactory) args[1]).newSelectStrategy(), (RejectedExecutionHandler) args[2]);}...
}

说明三:

创建NioEventLoop对象时,NioEventLoop的构造方法会通过调用其openSelector()方法来创建一个Selector,所以一个Selector就和一个NioEventLoop绑定了,而一个Selector可以将多个连接绑定在一起来负责监听这些连接的读写事件。

在NioEventLoop的openSelector()方法中,Netty会通过反射对Selector底层的数据结构进行优化(Hash Set => 数组)。

//SingleThreadEventLoop implementation which register the Channel's to a Selector and so does the multi-plexing of these in the event loop.
public final class NioEventLoop extends SingleThreadEventLoop {//The NIO Selector.Selector selector;private final SelectorProvider provider;private final SelectStrategy selectStrategy;...NioEventLoop(NioEventLoopGroup parent, Executor executor, SelectorProvider selectorProvider,SelectStrategy strategy, RejectedExecutionHandler rejectedExecutionHandler) {//调用其父类SingleThreadEventLoop的构造方法super(parent, executor, false, DEFAULT_MAX_PENDING_TASKS, rejectedExecutionHandler);if (selectorProvider == null) throw new NullPointerException("selectorProvider");if (strategy == null) throw new NullPointerException("selectStrategy");this.provider = selectorProvider;this.selector = openSelector();//创建一个Selectorthis.selectStrategy = strategy;}private Selector openSelector() {final Selector selector;try {selector = provider.openSelector();...} catch(IOException e) {...}...return selector;}...
}

说明四:

NioEventLoop的构造方法还会调用其父类的父类SingleThreadEventExecutor的构造方法。SingleThreadEventExecutor的构造方法里有两个关键的操作:一是把线程执行器保存起来,因为后面创建NioEventLoop对应的线程时要用到。二是创建一个MPSC任务队列,因为Netty中所有异步执行的本质都是通过该任务队列来协调完成的。

//Abstract base class for EventLoops that execute all its submitted tasks in a single thread.
public abstract class SingleThreadEventLoop extends SingleThreadEventExecutor implements EventLoop {private final Queue<Runnable> tailTasks;...protected SingleThreadEventLoop(EventLoopGroup parent, Executor executor, boolean addTaskWakesUp, int maxPendingTasks, RejectedExecutionHandler rejectedExecutionHandler) {//调用其父类SingleThreadEventExecutor的构造方法super(parent, executor, addTaskWakesUp, maxPendingTasks, rejectedExecutionHandler);//调用父类SingleThreadEventExecutor的newTaskQueue()方法tailTasks = newTaskQueue(maxPendingTasks);}...
}//Abstract base class for OrderedEventExecutor's that execute all its submitted tasks in a single thread.
public abstract class SingleThreadEventExecutor extends AbstractScheduledEventExecutor implements OrderedEventExecutor {private final boolean addTaskWakesUp;private final Executor executor;private final int maxPendingTasks;private final Queue<Runnable> taskQueue;private final RejectedExecutionHandler rejectedExecutionHandler;...//Create a new instanceprotectedSingleThreadEventExecutor(EventExecutorGroup parent, ThreadFactory threadFactory,boolean addTaskWakesUp, int maxPendingTasks, RejectedExecutionHandler rejectedHandler) {this(parent, new ThreadPerTaskExecutor(threadFactory), addTaskWakesUp, maxPendingTasks, rejectedHandler);}//Create a new instance//@param parent,the EventExecutorGroup which is the parent of this instance and belongs to it//@param executor,the Executor which will be used for executing//@param addTaskWakesUp,true if and only if invocation of #addTask(Runnable) will wake up the executor thread//@param maxPendingTasks,the maximum number of pending tasks before new tasks will be rejected.//@param rejectedHandler,the RejectedExecutionHandler to use.protected SingleThreadEventExecutor(EventExecutorGroup parent, Executor executor,boolean addTaskWakesUp, int maxPendingTasks, RejectedExecutionHandler rejectedHandler) {super(parent);this.addTaskWakesUp = addTaskWakesUp;this.maxPendingTasks = Math.max(16, maxPendingTasks);//关键操作一:把线程执行器保存起来this.executor = ObjectUtil.checkNotNull(executor, "executor");//关键操作二:创建一个MPSC任务队列this.taskQueue = newTaskQueue(this.maxPendingTasks);this.rejectedExecutionHandler = ObjectUtil.checkNotNull(rejectedHandler, "rejectedHandler");}//Create a new Queue which will holds the tasks to execute.//NioEventLoop会重写这个newTaskQueue()方法protected Queue<Runnable> newTaskQueue(int maxPendingTasks) {return new LinkedBlockingQueue<Runnable>(maxPendingTasks);}...
}//SingleThreadEventLoop implementation which register the Channel's to a Selector and so does the multi-plexing of these in the event loop.
public final class NioEventLoop extends SingleThreadEventLoop {...//创建一个MPSC任务队列@Overrideprotected Queue<Runnable> newTaskQueue(int maxPendingTasks) {//This event loop never calls takeTask()return PlatformDependent.newMpscQueue(maxPendingTasks);}...
}

MPSC队列也就是多生产者单消费者队列。单消费者是指某个NioEventLoop对应的线程(执行其run()方法的那个线程)。多生产者就是这个NioEventLoop对应的线程之外的线程,通常情况下就是我们的业务线程。比如,一些线程在调用writeAndFlush()方法时可以不用考虑线程安全而随意调用,那么这些线程就是多生产者。

MPSC队列是通过JCTools这个工具包来实现的,Netty的高性能很大程度上要归功于这个工具包。MPSC的全称是Muti Producer Single Consumer。Muti Producer对应的是外部线程,Single Consumer对应的是Netty的NioEventLoop线程。外部线程在执行Netty的一些任务时,如果判断不是由NioEventLoop对应的线程执行的,就会直接放入一个任务队列里,然后由一个NioEventLoop对应的线程去执行。

创建NioEventLoop总结:

NioEventLoopGroup的newChild()方法创建NioEventLoop时做了三项事情:一.创建一个Selector用于轮询注册到该NioEventLoop上的连接,二.创建一个MPSC任务队列,三.保存线程执行器到NioEventLoop。

(6)创建线程选择器EventExecutorChooser

说明一:

在传统的BIO编程中,一个新连接被创建后,通常需要给这个连接绑定一个Selector,之后这个连接的整个生命周期都由这个Selector管理。

说明二:

创建NioEventLoop时会创建一个Selector,所以一个Selector会对应一个NioEventLoop,一个NioEventLoop上会有一个Selector。线程选择器的作用就是为一个连接在NioEventLoopGroup中选择一个NioEventLoop,从而将该连接绑定到这个NioEventLoop的Selector上。

说明三:

根据MultithreadEventExecutorGroup的构造方法,会使用DefaultEventExecutorChooserFactory的newChooser()方法来创建线程选择器。创建好线程选择器EventExecutorChooser之后,便可以通过其next()方法获取一个NioEventLoop。

Netty通过判断NioEventLoopGroup中的NioEventLoop个数是否是2的幂来创建不同的线程选择器。但不管是哪一种选择器,最终效果都是从第一个NioEventLoop开始遍历到最后一个NioEventLoop,然后再从第一个NioEventLoop开始,如此循环。

//Abstract base class for EventExecutorGroup implementations that handles their tasks with multiple threads at the same time.
public abstract class MultithreadEventExecutorGroup extends AbstractEventExecutorGroup {private final EventExecutor[] children;private final EventExecutorChooserFactory.EventExecutorChooser chooser;...//Create a new instance.protected MultithreadEventExecutorGroup(int nThreads, Executor executor, Object... args) {this(nThreads, executor, DefaultEventExecutorChooserFactory.INSTANCE, 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 null if the default should be used.//@param chooserFactory,the EventExecutorChooserFactory to use.//@param args,arguments which will passed to each #newChild(Executor, Object...) callprotected MultithreadEventExecutorGroup(int nThreads, Executor executor, EventExecutorChooserFactory chooserFactory, Object... args) {if (nThreads <= 0) throw new IllegalArgumentException(String.format("nThreads: %d (expected: > 0)", nThreads));//1.创建ThreadPerTaskExecutor线程执行器if (executor == null) executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());//2.创建NioEventLoopchildren = new EventExecutor[nThreads];for (int i = 0; i < nThreads; i ++) {...//创建每一个NioEventLoop时,都会调用newChild()方法给每一个NioEventLoop配置一些核心参数//传入线程执行器executor去创建NioEventLoopchildren[i] = newChild(executor, args);}//3.创建线程选择器,chooserFactory就是传入的DefaultEventExecutorChooserFactory实例chooser = chooserFactory.newChooser(children);...}...
}//Default implementation which uses simple round-robin to choose next EventExecutor.
@UnstableApi
public final class DefaultEventExecutorChooserFactory implements EventExecutorChooserFactory {public static final DefaultEventExecutorChooserFactory INSTANCE = new DefaultEventExecutorChooserFactory();private DefaultEventExecutorChooserFactory() { }@SuppressWarnings("unchecked")@Overridepublic EventExecutorChooser newChooser(EventExecutor[] executors) {if (isPowerOfTwo(executors.length)) {//如果NioEventLoop个数是2的幂,则进行位与运算return new PowerOfTowEventExecutorChooser(executors);} else {//如果NioEventLoop个数不是2的幂,则进行普通取模运算return new GenericEventExecutorChooser(executors);}}private static boolean isPowerOfTwo(int val) {return (val & -val) == val;}private static final class PowerOfTowEventExecutorChooser implements EventExecutorChooser {private final AtomicInteger idx = new AtomicInteger();private final EventExecutor[] executors;PowerOfTowEventExecutorChooser(EventExecutor[] executors) {this.executors = executors;}@Overridepublic EventExecutor next() {return executors[idx.getAndIncrement() & executors.length - 1];}}private static final class GenericEventExecutorChooser implements EventExecutorChooser {private final AtomicInteger idx = new AtomicInteger();private final EventExecutor[] executors;GenericEventExecutorChooser(EventExecutor[] executors) {this.executors = executors;}@Overridepublic EventExecutor next() {return executors[Math.abs(idx.getAndIncrement() % executors.length)];}}
}

说明四:

创建NioEventLoopGroup的最后一个步骤就是创建线程选择器chooser,创建线程选择器的流程如下:

chooserFactory.newChooser() //创建线程选择器的入口,chooser的作用就是为新连接绑定一个NioEventLoopDefaultEventExecutorChooserFactory.isPowerOfTwo() //判断NioEventLoop个数是否为2的幂PowerOfTowEventExecutorChooser //优化index++ & (length - 1) //位与运算GenericEventExecutorChooser //普通abs(index++ % length) //取模运算

(7)NioEventLoopGroup的创建总结

默认情况下,NioEventLoopGroup会创建2倍CPU核数个NioEventLoop。一个NioEventLoop和一个Selector以及一个MPSC任务队列一一对应。

NioEventLoop线程的命名规则是nioEventLoopGroup-xx-yy,其中xx表示全局第xx个NioEventLoopGroup线程池,yy表示这个NioEventLoop在这个NioEventLoopGroup中是属于第yy个。

线程选择器chooser的作用是为一个连接选择一个NioEventLoop,可通过线程选择器的next()方法返回一个NioEventLoop。如果NioEventLoop的个数为2的幂,则next()方法会使用位与运算进行优化。

一个NioEventLoopGroup会有一个线程执行器executor、一个线程选择器chooser、一个数组children存放2倍CPU核数个NioEventLoop。

http://www.whsansanxincailiao.cn/news/32048076.html

相关文章:

  • 做网站本溪/网站seo招聘
  • 有什么网站可以做电子版邀请函/南宁seo公司哪家好
  • 商城网站开发周期/网站页面优化内容包括哪些
  • 网站建设与网页设计实训报告/房地产估价师考试
  • 网络教学平台登录/湖南企业seo优化推荐
  • 国外app界面设计网站/深圳网络营销平台
  • 南昌市公司网站建设/在哪里找专业推广团队
  • 宣武网站开发/电脑优化设置
  • 做网站和推广找哪家好/windows优化大师手机版
  • 怎样做约票的网站意思/微信小程序开发一个多少钱啊
  • 苏州建站公司哪个济南兴田德润实惠吗/新媒体seo培训
  • 在线网站做成app/广州网站排名优化报价
  • 设计之家微博/seopeixun com cn
  • 帝国cms手机网站教程/阿亮seo技术顾问
  • 花生壳一个端口做网站/产品营销方案
  • 开发一个网站平台多少钱/百度指数是搜索量吗
  • 灰产项目网/厦门百度seo
  • 塘厦网站建设/舆情分析报告
  • 公司网站优点/游戏推广话术
  • 住房和城乡建设部网站加装电梯/网课培训机构排名前十
  • 标准企业网站开发合同/模板建站哪里有
  • 网站项目评价/百度关键词搜索技巧
  • 江苏建筑工程网/域名年龄对seo的影响
  • 无锡网站建设公司/客服外包平台
  • 商丘网站建设有限公司/嘉兴网站建设制作
  • 网站开发合同书/企业培训有哪些方面
  • 网站 为何要 备案/百度导航最新版本下载安装
  • wordpress paypal转账/洛阳seo网站
  • 建设网站服务器选择/企业网站页面设计
  • 网站建设 开发票/全网关键词指数查询