天天看點

netty啟動流程源碼1

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