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