public static void main(String[] args) throws InterruptedException {
//就是一个死循环,不停地检测IO事件,处理IO事件,执行任务
//创建一个线程组:接受客户端连接 主线程
EventLoopGroup bossGroup=new NioEventLoopGroup(1);//cpu核心数*2
//创建一个线程组:接受网络操作 工作线程
EventLoopGroup workerGroup=new NioEventLoopGroup(); //cpu核心数*2
//是服务端的一个启动辅助类,通过给他设置一系列参数来绑定端口启动服务
ServerBootstrap serverBootstrap=new ServerBootstrap();
// 我们需要两种类型的人干活,一个是老板,一个是工人,老板负责从外面接活,
// 接到的活分配给工人干,放到这里,bossGroup的作用就是不断地accept到新的连接,将新的连接丢给workerGroup来处理
serverBootstrap.group(bossGroup,workerGroup)
//设置使用NioServerSocketChannel作为服务器通道的实现
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG,128) //设置线程队列中等待连接的个数
.childOption(ChannelOption.SO_KEEPALIVE,true)//保持活动连接状态
//表示服务器启动过程中,需要经过哪些流程,这里NettyTestHendler最终的顶层接口为ChannelHander,
// 是netty的一大核心概念,表示数据流经过的处理器
.handler(new NettyTestHendler())
//表示一条新的连接进来之后,该怎么处理,也就是上面所说的,老板如何给工人配活
.childHandler(new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
nioSocketChannel.pipeline().addLast(new StringDecoder(),new NettyServerHendler());
}
});
System.out.println(".........server init..........");
// 这里就是真正的启动过程了,绑定9090端口,等待服务器启动完毕,才会进入下行代码
ChannelFuture future = serverBootstrap.bind(9090).sync();
System.out.println(".........server start..........");
//等待服务端关闭socket
future.channel().closeFuture().sync();
// 关闭两组死循环
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
如上当我们创建一个:
EventLoopGroup bossGroup=new NioEventLoopGroup(1);
跟踪源码发现如下:
protected MultithreadEventLoopGroup(int nThreads, Executor executor, Object... args) {
//nThreads如果不传默认是0 如果是0的话 就获取CPU核数的两倍 DEFAULT_EVENT_LOOP_THREADS==CPU核数的两倍
super(nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads, executor, args);
}
如注释里写的:nThreads如果不传默认是0 如果是0的话 就获取CPU核数的两倍 DEFAULT_EVENT_LOOP_THREADS==CPU核数的两倍;这里这个值为1
继续跟踪到:
protected MultithreadEventExecutorGroup(int nThreads, Executor executor,
EventExecutorChooserFactory chooserFactory, Object... args) {
if (nThreads <= 0) {
throw new IllegalArgumentException(String.format("nThreads: %d (expected: > 0)", nThreads));
}
if (executor == null) {
//newDefaultThreadFactory()=线程工厂 专门创建线程的
//newDefaultThreadFactory()调用的是 MultithreadEventLoopGroup.newDefaultThreadFactory()
//最终创建的是DefaultThreadFactory,他实现了继承自jdk的ThreadFactory
executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
}
//nThreads如果不传默认是0 如果是0的话 就获取CPU核数的两倍 DEFAULT_EVENT_LOOP_THREADS==CPU核数的两倍
children = new EventExecutor[nThreads];
for (int i = 0; i < nThreads; i ++) {
//出现异常标识
boolean success = false;
try {
//创建nThreads个nioEventLoop保存到children数组中
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;
}
}
}
}
}
可以看出创建了一个数组 children = new EventExecutor[nThreads];
然后for循环赋值:这样
MultithreadEventExecutorGroup这个类的属性private final EventExecutor[] children 里面的值就是EventExecutor的实现类
继续跟踪发现存的是NioEventLoop这个对象;且调用的构造方法如下:
NioEventLoop(NioEventLoopGroup parent, Executor executor, SelectorProvider selectorProvider,
SelectStrategy strategy, RejectedExecutionHandler rejectedExecutionHandler) {
//NioEventLoopGroup.this
//executor=new ThreadPerTaskExecutor(newDefaultThreadFactory());
//SelectorProvider ServerSocketChannel就是通过ServerSocketChannel.open()==》 SelectorProvider.provider().openServerSocketChannel()创建的
//strategy=DefaultSelectStrategyFactory.INSTANCE===》new DefaultSelectStrategyFactory()
//rejectedExecutionHandler=RejectedExecutionHandlers.reject() ===》 new 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.provider()
provider = selectorProvider;
final SelectorTuple selectorTuple = openSelector();
//替换了数据结构selectedKeys publicSelectedKeys的原生selector
selector = selectorTuple.selector;
//子类包装的selector 底层数据结构也是被替换了的
unwrappedSelector = selectorTuple.unwrappedSelector;
//selectStrategy=new DefaultSelectStrategyFactory()
selectStrategy = strategy;
}
这里主要做的功能是netty做了优化:
把原生jdk中selector类中的selectedKeys publicSelectedKeys 的属性类型从set集合变成用数组替代
总结:在创建NioEventLoopGroup的时候主要的是根据参数去创建多少个selector