Netty源码-EventLoop分析

Netty源码-EventLoop分析

一、EventLoop作用

核心作用:IO操作(accept、read、Write),普通任务、定时任务
组成:EventLoop中封装了Selector、Thread、任务队列

二、EventLoop的类关系图

在这里插入图片描述

在NioEventLoop中有三个属性  
 	private Selector selector;
    private Selector unwrappedSelector;
    private SelectedSelectionKeySet selectedKeys;
在 SingleThreadEventExecutor中封装了队列和线程
    private final Queue<Runnable> taskQueue;
    private volatile Thread thread;
属性标志着这个类拥有什么功能,因此从他的属性可以知道这个类拥有什么功能,说明EventLoop这个类是对Thread、Queue、Thread的封装。

问题:为什么会在NioEventLoop中提供两个Selector属性,分别为selector和unwrappedSelector为什么?

	select是对unWrappedSelector的进一步封装,原始的unWrappedSelector的unWrappedSelector是采用set()集合存储的,这样查询的效率相对较低,而Nettyd对Select进行了重构,采用了List几个进行存储,List的遍历速度相对于Set要快特别多。

三、Selector的创建时机

Selector的创建是在NioEventLoop()的构造方法中创建的

在这里插入图片描述

NioEventLoop.openSelector()方法

   private SelectorTuple openSelector() {
        final Selector unwrappedSelector;
        try {
            //1、创建Selector,这个创建方式和原始Nio中Selector的创建方式是一样的
            unwrappedSelector = provider.openSelector();
        } catch (IOException e) {
            throw new ChannelException("failed to open a new selector", e);
        }

        if (DISABLE_KEY_SET_OPTIMIZATION) {
            return new SelectorTuple(unwrappedSelector);
        }

        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;
                }
            }
        });

        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;
        final SelectedSelectionKeySet selectedKeySet = new SelectedSelectionKeySet();

        Object maybeException = AccessController.doPrivileged(new PrivilegedAction<Object>() {
            @Override
            public Object run() {
                try {
                    Field selectedKeysField = selectorImplClass.getDeclaredField("selectedKeys");
                    Field publicSelectedKeysField = selectorImplClass.getDeclaredField("publicSelectedKeys");

                    if (PlatformDependent.javaVersion() >= 9 && PlatformDependent.hasUnsafe()) {
                        // Let us try to use sun.misc.Unsafe to replace the SelectionKeySet.
                        // This allows us to also do this in Java9+ without any extra flags.
                        long selectedKeysFieldOffset = PlatformDependent.objectFieldOffset(selectedKeysField);
                        long publicSelectedKeysFieldOffset =
                                PlatformDependent.objectFieldOffset(publicSelectedKeysField);

                        if (selectedKeysFieldOffset != -1 && publicSelectedKeysFieldOffset != -1) {
                            PlatformDependent.putObject(
                                    unwrappedSelector, selectedKeysFieldOffset, selectedKeySet);
                            PlatformDependent.putObject(
                                    unwrappedSelector, publicSelectedKeysFieldOffset, selectedKeySet);
                            return null;
                        }
                        // We could not retrieve the offset, lets try reflection as last-resort.
                    }
                    //2、采用反射的方式将原始Selector中的selectedKeys、publicSelectedKeys设置到新创建的Selector中
                    Throwable cause = ReflectionUtil.trySetAccessible(selectedKeysField, true);
                    if (cause != null) {
                        return cause;
                    }
                    cause = ReflectionUtil.trySetAccessible(publicSelectedKeysField, true);
                    if (cause != null) {
                        return cause;
                    }

                    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);
        }
        selectedKeys = selectedKeySet;
        logger.trace("instrumented a special java.util.Set into: {}", unwrappedSelector);
        return new SelectorTuple(unwrappedSelector,
                                 new SelectedSelectionKeySetSelector(unwrappedSelector, selectedKeySet));
    }

这个方法首先采用原始Nio的方式将Selector进行创建出来,创建完成之后,采用反射的方式将selectedKeys、publicSelectedKeys设置到新创建的Selector中。

四、EventLoop处理任务

EventLoop主要可以处理IO任务、普通任务、定时任务

EventLoop处理普通任务

在这里插入图片描述

SingleThreadEventExecutor.execute()

    private void execute(Runnable task, boolean immediate) {
        //1、判断当前线程是否为NIO线程
        boolean inEventLoop = inEventLoop();
        //2、将任务添加到任务队列里面
        addTask(task);
        if (!inEventLoop) {
            //3、不是NIO线程开启一个新的线程
            startThread();
            if (isShutdown()) {
                boolean reject = false;
                try {
                    if (removeTask(task)) {
                        reject = true;
                    }
                } catch (UnsupportedOperationException e) {
                }
                if (reject) {
                    reject();
                }
            }
        }

        if (!addTaskWakesUp && immediate) {
            wakeup(inEventLoop);
        }
    }

startThread()

    private void startThread() {
       //1、state的初始化值为1 ST_NOT_STARTED的初始化值为1
        if (state == ST_NOT_STARTED) {
           //2、将state的值增加一,然后开始创建新的线程,表示只会创建一次NIO线程
            if (STATE_UPDATER.compareAndSet(this, ST_NOT_STARTED, ST_STARTED)) {
                boolean success = false;
                try {
                    doStartThread();
                    success = true;
                } finally {
                    if (!success) {
                        STATE_UPDATER.compareAndSet(this, ST_STARTED, ST_NOT_STARTED);
                    }
                }
            }
        }
    }

doStartThread()创建线程

    private void doStartThread() {
        assert thread == null;
        //1、创建一个Nio线程
        executor.execute(new Runnable() {
            @Override
            public void run() {
                thread = Thread.currentThread();
                if (interrupted) {
                    thread.interrupt();
                }

                boolean success = false;
                updateLastExecutionTime();
                try {
                   //2、通过EventLoop线程执行IO操作,普通任务 定时任务
                    SingleThreadEventExecutor.this.run();
                    success = true;
                } catch (Throwable t) {
                    logger.warn("Unexpected exception from an event executor: ", t);
                } finally {
                    for (;;) {
                        int oldState = state;
                        if (oldState >= ST_SHUTTING_DOWN || STATE_UPDATER.compareAndSet(
                                SingleThreadEventExecutor.this, oldState, ST_SHUTTING_DOWN)) {
                            break;
                        }
                    }

                    // Check if confirmShutdown() was called at the end of the loop.
                    if (success && gracefulShutdownStartTime == 0) {
                        if (logger.isErrorEnabled()) {
                            logger.error("Buggy " + EventExecutor.class.getSimpleName() + " implementation; " +
                                    SingleThreadEventExecutor.class.getSimpleName() + ".confirmShutdown() must " +
                                    "be called before run() implementation terminates.");
                        }
                    }

                    try {
                        for (;;) {
                            if (confirmShutdown()) {
                                break;
                            }
                        }

                        for (;;) {
                            int oldState = state;
                            if (oldState >= ST_SHUTDOWN || STATE_UPDATER.compareAndSet(
                                    SingleThreadEventExecutor.this, oldState, ST_SHUTDOWN)) {
                                break;
                            }
                        }

                        confirmShutdown();
                    } finally {
                        try {
                            cleanup();
                        } finally {
                            FastThreadLocal.removeAll();

                            STATE_UPDATER.set(SingleThreadEventExecutor.this, ST_TERMINATED);
                            threadLock.countDown();
                            int numUserTasks = drainTasks();
                            if (numUserTasks > 0 && logger.isWarnEnabled()) {
                                logger.warn("An event executor terminated with " +
                                        "non-empty task queue (" + numUserTasks + ')');
                            }
                            terminationFuture.setSuccess(null);
                        }
                    }
                }
            }
        });
    }

SingleThreadEventExecutor.this.run();

    protected void run() {
        int selectCnt = 0;
        for (;;) {
            try {
                int strategy;
                try {
                   //1、这是一个策略,判断普通任务队列里面是否有任务,有个有普通任务调用slectNow()非阻塞
                   //的方式运行,如果没有则返回SelectStrategy.SELECT
                    strategy = selectStrategy.calculateStrategy(selectNowSupplier, hasTasks());
                    switch (strategy) {
                    case SelectStrategy.CONTINUE:
                        continue;

                    case SelectStrategy.BUSY_WAIT:
                        // fall-through to SELECT since the busy-wait is not supported with NIO

                    //2、以上两个case一般不会走,会走这个的表示,普通任务队列为空,那么这个任务就可能为
                    //定时任务或者IO任务
                    case SelectStrategy.SELECT:
                        //获取定时任务的延迟时间,如果没有则返回-1
                        long curDeadlineNanos = nextScheduledTaskDeadlineNanos();
                        //如果返回-1则表示没有,设置curDeadlineNanos 为Long.MAX_VALUE
                        if (curDeadlineNanos == -1L) {
                            curDeadlineNanos = NONE; // nothing on the calendar
                        }
                        nextWakeupNanos.set(curDeadlineNanos);
                        try {
                             //能走到这表示普通任务队列肯定是为空的,那么hasTasks()返回false,                        
                             //则!hasTasks()一定为True,则一定会走这个方法
                            if (!hasTasks()) {
                                //没有定时任务则阻塞,如果有定时任务,延时到定时任务开始时唤醒
                                strategy = select(curDeadlineNanos);
                            }
                        } finally {
                            // This update is just to help block unnecessary selector wakeups
                            // so use of lazySet is ok (no race condition)
                            nextWakeupNanos.lazySet(AWAKE);
                        }
                        // fall through
                    default:
                    }
                } catch (IOException e) {
                    // If we receive an IOException here its because the Selector is messed up. Let's rebuild
                    // the selector and retry. https://github.com/netty/netty/issues/8566
                    rebuildSelector0();
                    selectCnt = 0;
                    handleLoopException(e);
                    continue;
                }
                
                selectCnt++;
                cancelledKeys = 0;
                needsToSelectAgain = false;
                //IORatio IO比率为50
                final int ioRatio = this.ioRatio;
                boolean ranTasks;
                //ioRatio 默认为50,这里一般不会走
                if (ioRatio == 100) {
                    try {
                        if (strategy > 0) {
                            processSelectedKeys();
                        }
                    } finally {
                        // Ensure we always run tasks.
                        ranTasks = runAllTasks();
                    }
                } else if (strategy > 0) {
                    final long ioStartTime = System.nanoTime();
                    try {
                        //重要:处理IO任务
                        processSelectedKeys();
                    } finally {
                        // Ensure we always run tasks.
                        final long ioTime = System.nanoTime() - ioStartTime;
                        //处理普通任务  
                        //注意: IO操作一定要都完成普通任务操作到了时间结束,即使没有做完,也结束
                        ranTasks = runAllTasks(ioTime * (100 - ioRatio) / ioRatio);
                    }
                } else {
                    ranTasks = runAllTasks(0); // This will run the minimum number of tasks
                }

                if (ranTasks || strategy > 0) {
                    if (selectCnt > MIN_PREMATURE_SELECTOR_RETURNS && logger.isDebugEnabled()) {
                        logger.debug("Selector.select() returned prematurely {} times in a row for Selector {}.",
                                selectCnt - 1, selector);
                    }
                    selectCnt = 0;
                } else if (unexpectedSelectorWakeup(selectCnt)) { // Unexpected wakeup (unusual case)
                    selectCnt = 0;
                }
            } catch (CancelledKeyException e) {
                // Harmless exception - log anyway
                if (logger.isDebugEnabled()) {
                    logger.debug(CancelledKeyException.class.getSimpleName() + " raised by a Selector {} - JDK bug?",
                            selector, e);
                }
            } catch (Throwable t) {
                handleLoopException(t);
            }
            // Always handle shutdown even if the loop processing threw an exception.
            try {
                if (isShuttingDown()) {
                    closeAll();
                    if (confirmShutdown()) {
                        return;
                    }
                }
            } catch (Throwable t) {
                handleLoopException(t);
            }
        }
    }

processSelectedKeys()处理IO任务

在这里插入图片描述
在这里插入图片描述

遍历SelectedKeys并且执行processSelectedKey()

在这里插入图片描述

processSelectedKey()

    private void processSelectedKey(SelectionKey k, AbstractNioChannel ch) {
         //ch为ServerSocketChannel或者SocketChannel
        final AbstractNioChannel.NioUnsafe unsafe = ch.unsafe();
        if (!k.isValid()) {
            final EventLoop eventLoop;
            try {
                eventLoop = ch.eventLoop();
            } catch (Throwable ignored) {
                return;
            }
            if (eventLoop == this) {
                unsafe.close(unsafe.voidPromise());
            }
            return;
        }

        try {
            int readyOps = k.readyOps();
            //1、处理OP_CONNECT事件
            if ((readyOps & SelectionKey.OP_CONNECT) != 0) {
                int ops = k.interestOps();
                ops &= ~SelectionKey.OP_CONNECT;
                k.interestOps(ops);

                unsafe.finishConnect();
            }
            //2、处理OP_WRITE事件
            if ((readyOps & SelectionKey.OP_WRITE) != 0) {
                ch.unsafe().forceFlush();
            }
            //3、处理OP_ACCEPT或者OP_READ 事件
            if ((readyOps & (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0 || readyOps == 0) {
                unsafe.read();
            }
        } catch (CancelledKeyException ignored) {
            unsafe.close(unsafe.voidPromise());
        }
    }
站在ServerSocketChannel角度,发现Accept事件之后要进行
      //1、获取SocketChannel
       SocketChannel sc = channel.accept();
       //2、设置非阻塞
        sc.configureBlocking(false);
        //3、selector监听
        SelectionKey selectionKey = sc.register(selector, 0, null);
        //4、设置监听事件
        selectionKey.interestOps(SelectionKey.OP_READ);

在这里插入图片描述

五、Netty怎么处理IO Read操作

1、服务端代码

public class NettyServer {

    private static final Logger log = LoggerFactory.getLogger(NettyServer.class);


    public static void main(String[] args) {
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        serverBootstrap.channel(NioServerSocketChannel.class);

        NioEventLoopGroup bossGroup = new NioEventLoopGroup();
        NioEventLoopGroup workerGroup = new NioEventLoopGroup();
//        serverBootstrap.childOption()
        final LoggingHandler loggingHandler = new LoggingHandler();
        try {
            serverBootstrap.group(bossGroup, workerGroup);
            //设置IO ByteBuffer大小
           serverBootstrap.childHandler(new ChannelInitializer<NioSocketChannel>() {
               @Override
               protected void initChannel(NioSocketChannel ch) throws Exception {
                   ch.pipeline().addLast(new LoggingHandler());
               }
           });
            Channel channel = serverBootstrap.bind(8080).sync().channel();
            channel.closeFuture().sync();
        } catch (InterruptedException e) {
            log.debug("server error is {}", e);
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

2、客户端代码

public class NettyClient {

    private static final Logger log = LoggerFactory.getLogger(NettyClient.class);

    public static void main(String[] args) {
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.channel(NioSocketChannel.class);
        NioEventLoopGroup group = new NioEventLoopGroup();
        try {
            bootstrap.group(group);
            bootstrap.handler(new ChannelInitializer<NioSocketChannel>() {
                @Override
                protected void initChannel(final NioSocketChannel ch) throws Exception {
                    ChannelPipeline pipeline = ch.pipeline();
                    pipeline.addLast(new LoggingHandler());
                    pipeline.addLast(new ChannelInboundHandlerAdapter(){
                        @Override
                        public void channelActive(ChannelHandlerContext ctx) throws Exception {
                            ByteBuf buffer = ctx.alloc().buffer();
                            buffer.writeCharSequence("hello,hezhenbin", Charset.defaultCharset());
                            ctx.writeAndFlush(buffer);
                        }
                    });
                    };
                });
            Channel channel = bootstrap.connect(new InetSocketAddress(8080)).sync().channel();
            channel.closeFuture().sync();
        } catch (InterruptedException e) {
            log.debug("client error is {}", e);
        } finally {
            group.shutdownGracefully();
        }

    }
}

3、打断点在监听事务的方法

在这里插入图片描述

4、第一次处理的是accept的事件,然后处理AbstractNioMessageChannel.read()

        @Override
        public void read() {
            assert eventLoop().inEventLoop();
            //获取配置
            final ChannelConfig config = config();
            //获取pipeline 
            final ChannelPipeline pipeline = pipeline();
            final RecvByteBufAllocator.Handle allocHandle = unsafe().recvBufAllocHandle();
            allocHandle.reset(config);

            boolean closed = false;
            Throwable exception = null;
            try {
                try {
                    do {
                        //1、封装成NioSocketChannel
                        //2、将SocketChannel存储到NioSocketChannel
                        //3、将原始的SocketChannel设置为非阻塞
                        //4、将ServerSocketCHannel设置成为parent
                        int localRead = doReadMessages(readBuf);
                        if (localRead == 0) {
                            break;
                        }
                        if (localRead < 0) {
                            closed = true;
                            break;
                        }
                        allocHandle.incMessagesRead(localRead);
                    } while (allocHandle.continueReading());
                } catch (Throwable t) {
                    exception = t;
                }
                //readBuf保存的是NioSocketChannel
                int size = readBuf.size();
                //遍历所有的NioSocketChannel
                for (int i = 0; i < size; i ++) {
                    readPending = false;
                    //调用NioSocketChannel中pipeline的ChannelRead()方法,
                    //在accept阶段的时候,这时候pipline中主要有三个Handler
                    //主要是Head、ServerBootstrapAcceptor()、和Tail,因此调用的顺序为 
                    //head---->ServerBootstrapAcceptor------>Tail
                    //因为HeadContext中的ChannelRead只有 ctx.fireChannelRead(msg);
                    //因此直接传到下一个Handler为ServerBootstrapAcceptor
                    pipeline.fireChannelRead(readBuf.get(i));
                }
                readBuf.clear();
                allocHandle.readComplete();
                pipeline.fireChannelReadComplete();

                if (exception != null) {
                    closed = closeOnReadError(exception);

                    pipeline.fireExceptionCaught(exception);
                }

                if (closed) {
                    inputShutdown = true;
                    if (isOpen()) {
                        close(voidPromise());
                    }
                }
            } finally {
                if (!readPending && !config.isAutoRead()) {
                    removeReadOp();
                }
            }
        }
    }

在 ServerBootstrap.channelRead()中打上debug,上面放行过了 pipeline.fireChannelRead(readBuf.get(i));

在这里插入图片描述

childGroup.register(child),EventLoop开启一个新线程进行注册,调用AbstractChannel.register()

    @Override
        public final void register(EventLoop eventLoop, final ChannelPromise promise) {
            ObjectUtil.checkNotNull(eventLoop, "eventLoop");
            if (isRegistered()) {
                promise.setFailure(new IllegalStateException("registered to an event loop already"));
                return;
            }
            if (!isCompatible(eventLoop)) {
                promise.setFailure(
                        new IllegalStateException("incompatible event loop type: " + eventLoop.getClass().getName()));
                return;
            }

            AbstractChannel.this.eventLoop = eventLoop;

            if (eventLoop.inEventLoop()) {
                register0(promise);
            } else {
                try {
                   //EventLoop开启一个新的线程执行注册操作
                    eventLoop.execute(new Runnable() {
                        @Override
                        public void run() {
                            register0(promise);
                        }
                    });
                } catch (Throwable t) {
                    logger.warn(
                            "Force-closing a channel whose registration task was not accepted by an event loop: {}",
                            AbstractChannel.this, t);
                    closeForcibly();
                    closeFuture.setClosed();
                    safeSetFailure(promise, t);
                }
            }
        }

执行AbstractChannel中的register0方法

        private void register0(ChannelPromise promise) {
            try {
                if (!promise.setUncancellable() || !ensureOpen(promise)) {
                    return;
                }
                boolean firstRegistration = neverRegistered;
                //注册SocketChannel ChannelInitializer下的initChannel方法
                doRegister();
                neverRegistered = false;
                registered = true;
                //回调我们在服务端中写的
                pipeline.invokeHandlerAddedIfNeeded();
                safeSetSuccess(promise);
                pipeline.fireChannelRegistered();

                if (isActive()) {
                    if (firstRegistration) {
                        //调用pipline中的所有ChannelActive()方法进行事件的注册,主要在HeadContext中的
                        //ChannelActive()方法中,在HeadContext下打下断点
                        pipeline.fireChannelActive();
                    } else if (config().isAutoRead()) {
                        beginRead();
                    }
                }
            } catch (Throwable t) {
                // Close the channel directly to avoid FD leak.
                closeForcibly();
                closeFuture.setClosed();
                safeSetFailure(promise, t);
            }
        }

HeadContext.ChannelActive操作

在这里插入图片描述

AbstractNioChannel.doBeginRead()进行Read事件注册

在这里插入图片描述
至此完成SocketChannel中Read事件的监听。

当监听到Read事件之后

NioEventLoop.read()

在这里插入图片描述

AbstractNioByteChannel.read()

        @Override
        public final void read() {
            final ChannelConfig config = config();
            if (shouldBreakReadReady(config)) {
                clearReadPending();
                return;
            }
            final ChannelPipeline pipeline = pipeline();
            final ByteBufAllocator allocator = config.getAllocator();
            final RecvByteBufAllocator.Handle allocHandle = recvBufAllocHandle();
            allocHandle.reset(config);

            ByteBuf byteBuf = null;
            boolean close = false;
            try {
                do {
                   //1、创建ByteBuffer用于接收客户端写的数据
                    byteBuf = allocHandle.allocate(allocator);
                    //2、doReadBytes(byteBuf)这个方法执行完成后,ByteBuffer就存储了
                    //对应数据
                    allocHandle.lastBytesRead(doReadBytes(byteBuf));
                    if (allocHandle.lastBytesRead() <= 0) {
                        // nothing was read. release the buffer.
                        byteBuf.release();
                        byteBuf = null;
                        close = allocHandle.lastBytesRead() < 0;
                        if (close) {
                            readPending = false;
                        }
                        break;
                    }

                    allocHandle.incMessagesRead(1);
                    readPending = false;
                    //3、触发所有handler中的ChannelRead方法
                    pipeline.fireChannelRead(byteBuf);
                    byteBuf = null;
                } while (allocHandle.continueReading());
               
                allocHandle.readComplete();
                //4、触发所有handler中的ChannelReadComplete()方法
                pipeline.fireChannelReadComplete();

                if (close) {
                    closeOnRead(pipeline);
                }
            } catch (Throwable t) {
                handleReadException(pipeline, byteBuf, t, close, allocHandle);
            } finally {
                if (!readPending && !config.isAutoRead()) {
                    removeReadOp();
                }
            }
        }
    }

1、为什么在读取客户端传输过来的数据,要用do while循环进行读取的?

	为了防止ByteBuf的大小,不能一次性将客户端的数据都读完

这个pipeline.fireChannelRead(byteBuf);在循环体内部,会被多次调用,那么是不是等同于客户端发送了多次数据。

	不是

3、doReadBytes(byteBuf)读数据,将数据读到ByteBuffer

    protected int doReadBytes(ByteBuf byteBuf) throws Exception {
    //1、获取ByteBuffer的分配器
        final RecvByteBufAllocator.Handle allocHandle = unsafe().recvBufAllocHandle();
        //2、试图把ByteBuf中的可用空间全占满,尝试的目的是为了动态的调整ByteBuffer,
        //将ByteBuffer的可写量保存一份
        allocHandle.attemptedBytesRead(byteBuf.writableBytes());
        //3、通过java原生的SocketChnnel往ByteBuffer中写数据,写了多少数据
        //作为doReadBytes()的返回值
        return byteBuf.writeBytes(javaChannel(), allocHandle.attemptedBytesRead());
    }

4、这个allocHandle.continueReading()什么时候结束?

 private final UncheckedBooleanSupplier defaultMaybeMoreSupplier = new UncheckedBooleanSupplier() {
            @Override
            public boolean get() {
                //lastBytesRead表示这次实际读到的数据
                //attemptedBytesRead 表示ByteBuffer的可写容量
                //true 当前这个读到的数据,把ByteBuffer写满了
                //false 当前这个读到的数据,ByteBuffer没有写满
                return attemptedBytesRead == lastBytesRead;
            }
        };

       @Override
        public boolean continueReading() {
            return continueReading(defaultMaybeMoreSupplier);
        }

  private final boolean respectMaybeMoreData = DefaultMaxMessagesRecvByteBufAllocator.this.respectMaybeMoreData;
  private volatile boolean respectMaybeMoreData = true;
       @Override
        public boolean continueReading(UncheckedBooleanSupplier maybeMoreDataSupplier) {
            //config.isAutoRead()默认为true
            //respectMaybeMoreData默认也为true 则!respectMaybeMoreData为false
            //maybeMoreDataSupplier.get()调用上面的get()方法,表示查看ByteBuffer
            //是否写满
            //totalMessages表示这个循环的次数
            //maxMessagePerRead 16
            //totalMessages < maxMessagePerRead表示最多这个循环执行16次
            //16次如果没有完成就退出了,但是selector继续监听read 可以下一次再搞
            return config.isAutoRead() &&
                   (!respectMaybeMoreData || maybeMoreDataSupplier.get()) &&
                   totalMessages < maxMessagePerRead &&
                   totalBytesRead > 0;
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值