Netty服务端源码阅读笔记(三)new NioEventLoop(1)

16 篇文章 0 订阅

继承关系

虽然也实现了EventLoopGroup接口,但是不是一个组,是单个的Executor

上节看到NioEventLoopGroup的newChild方法实例化EventLoop数组

   protected EventLoop newChild(Executor executor, Object... args) throws Exception {
        return new NioEventLoop(this, executor, (SelectorProvider) args[0],
            ((SelectStrategyFactory) args[1]).newSelectStrategy(), (RejectedExecutionHandler) args[2]);
    }

new NioEventLoop()

    NioEventLoop(NioEventLoopGroup parent, Executor executor, SelectorProvider selectorProvider,
                 SelectStrategy strategy, RejectedExecutionHandler 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;
        final SelectorTuple selectorTuple = openSelector();
        selector = selectorTuple.selector;
        unwrappedSelector = selectorTuple.unwrappedSelector;
        selectStrategy = strategy;
    }

   private SelectorTuple openSelector() {
        // 这与NIO中的Selector.open()方法相同
        final Selector unwrappedSelector = provider.openSelector();
        // 我忽略了很多代码,关系netty对selector的优化,另外写写
         return new SelectorTuple(unwrappedSelector,
                                 new SelectedSelectionKeySetSelector(unwrappedSelector, selectedKeySet));
   }

  private static final class SelectorTuple {
        final Selector unwrappedSelector;
        final Selector selector;

        SelectorTuple(Selector unwrappedSelector) {
            this.unwrappedSelector = unwrappedSelector;
            this.selector = unwrappedSelector;
        }

        SelectorTuple(Selector unwrappedSelector, Selector selector) {
            this.unwrappedSelector = unwrappedSelector;
            this.selector = selector;
        }
    }

父类SingleThreadEventLoop

    protected SingleThreadEventLoop(EventLoopGroup parent, Executor executor,
                                    boolean addTaskWakesUp, int maxPendingTasks,
                                    RejectedExecutionHandler rejectedExecutionHandler) {
        super(parent, executor, addTaskWakesUp, maxPendingTasks, rejectedExecutionHandler);
        tailTasks = newTaskQueue(maxPendingTasks);
    }

    protected Queue<Runnable> newTaskQueue(int maxPendingTasks) {
        return new LinkedBlockingQueue<Runnable>(maxPendingTasks);
    }

父类SingleThreadEventExecutor

   protected SingleThreadEventExecutor(EventExecutorGroup parent, Executor executor,
                                        boolean addTaskWakesUp, int maxPendingTasks,
                                        RejectedExecutionHandler rejectedHandler) {
        // 不往上看了,就是关联当前NioEventLoop和NioEventLoopGroup
        super(parent);

        this.addTaskWakesUp = addTaskWakesUp;

        this.maxPendingTasks = Math.max(16, maxPendingTasks);

        // 每个NioEventLoop对象有一个内部的执行器Executor
        // 传入的参数executor是Group中初始化的new ThreadPerTaskExecutor(newDefaultThreadFactory());
        // this是当前NioEventLoop
        this.executor = ThreadExecutorMap.apply(executor, this);

        // 与上边的队列tailTasks 不是一个
        taskQueue = newTaskQueue(this.maxPendingTasks);

        // 拒绝策略非空校验
        rejectedExecutionHandler = ObjectUtil.checkNotNull(rejectedHandler, "rejectedHandler");
    }

每个NioEventLoop既实现了Executor接口,内部又有一个Executor对象(很多execute()方法,因此调用的是哪个的方法这点要明确)

先看内部的Executor对象是什么,入参executor是Group中初始化的ThreadPerTaskExecutor,eventExecutor 当前NioEventLoop

   public static Executor apply(final Executor executor, final EventExecutor eventExecutor) {
        ObjectUtil.checkNotNull(executor, "executor");
        ObjectUtil.checkNotNull(eventExecutor, "eventExecutor");
        return new Executor() {
            @Override
            public void execute(final Runnable command) {
                executor.execute(apply(command, eventExecutor));
            }
        };
    }

    public static Runnable apply(final Runnable command, final EventExecutor eventExecutor) {
        ObjectUtil.checkNotNull(command, "command");
        ObjectUtil.checkNotNull(eventExecutor, "eventExecutor");
        return new Runnable() {
            @Override
            public void run() {
                // 把eventExecutor对象设置到ThreadLocal变量中
                setCurrentEventExecutor(eventExecutor);
                try {
                    command.run();
                } finally {
                    setCurrentEventExecutor(null);
                }
            }
        };
    }

即内部的Executor对象的execute方法实际是 调用Group中实例化的ThreadPerTaskExecutor的execute方法来执行传入的command任务,可以先简单理解为新建线程执行command

public final class ThreadPerTaskExecutor implements Executor {
    private final ThreadFactory threadFactory;

    @Override
    public void execute(Runnable command) {
        threadFactory.newThread(command).start();
    }
}

再看NioEventLoop.execute()方法

方法在父类SingleThreadEventExecutor#execute

SingleThreadEventExecutor中有个state变量记录当前线程状态

private static final int ST_NOT_STARTED = 1;
private static final int ST_STARTED = 2;
private static final int ST_SHUTTING_DOWN = 3;
private static final int ST_SHUTDOWN = 4;
private static final int ST_TERMINATED = 5;

private volatile int state = ST_NOT_STARTED;
   public void execute(Runnable task) {
        if (task == null) {
            throw new NullPointerException("task");
        }

        // 判断eventLoop中的线程是否已经启动
        boolean inEventLoop = inEventLoop();

        // 给任务队列增加任务
        addTask(task);

        if (!inEventLoop) {
            // 如果EventLoop中的线程未启动,启动线程
            startThread();

            // 如果线程终止了
            if (isShutdown()) {
                boolean reject = false;
                try {
                    if (removeTask(task)) {
                        reject = true;
                    }
                } catch (UnsupportedOperationException e) {
                    // The task queue does not support removal so the best thing we can do is to just move on and
                    // hope we will be able to pick-up the task before its completely terminated.
                    // In worst case we will log on termination.
                }
                if (reject) {
                    // 上章的拒绝策略,报错
                    reject();
                }
            }
        }

        // addTaskWakesUp变量为false,是new NioEventLoop构造函数中传入的
        // wakesUpForTask返回true,即每次添加任务,eventLoop中的线程就被唤醒,被从select()阻塞状态唤醒
        if (!addTaskWakesUp && wakesUpForTask(task)) {
           // 此方法暂时不管,知道是唤醒就成,下章细讲
            wakeup(inEventLoop);
        }
    }

    // NioEventLoop中如果线程启动,会执行this.thread = Thread.currentThread();
    // 因此此方法来判断,是否NioEventLoop已经开始执行
    public boolean inEventLoop() {
        return inEventLoop(Thread.currentThread());
    }
    public boolean inEventLoop(Thread thread) {
        return thread == this.thread;
    }

   protected void addTask(Runnable task) {
        if (task == null) {
            throw new NullPointerException("task");
        }
        if (!offerTask(task)) {
            reject(task);
        }
    }

    final boolean offerTask(Runnable task) {
        if (isShutdown()) {
            reject();
        }
        return taskQueue.offer(task);
    }

    @SuppressWarnings("unused")
    protected boolean wakesUpForTask(Runnable task) {
        return true;
    }

总的来看NioEventLoop.execute(Runnable a) 就是将任务放入任务队列,如果当前eventLoop还没有启动,创建线程并绑定线程到eventLoop

还有个小点要清楚,看代码虽然看到这,但是在new NioEventLoop的时候,NioEventLoop.execute并没有执行,内部绑定的线程并没有创建,何时创建的,在下一章ServerBootStrap

来看启动线程方法SingleThreadEventExecutor#startThread, 启动线程,启动之后执行NioEventLoop的run方法,run中会处理任务队列中的任务以及监听channel的事件

   private void startThread() {
        if (state == ST_NOT_STARTED) {
            // 线程状态为未启动,cas更新成功后正式开始启动
            if (STATE_UPDATER.compareAndSet(this, ST_NOT_STARTED, ST_STARTED)) {
                // 一旦启动后,再次调用NioEventLoop.execute就只是往任务队列加任务了
                try {
                    doStartThread();
                } catch (Throwable cause) {
                    STATE_UPDATER.set(this, ST_NOT_STARTED);
                    PlatformDependent.throwException(cause);
                }
            }
        }
    }

   private void doStartThread() {
        assert thread == null;
        // 这个executor是NioEventLoop的内部执行器,execute方法就是新建线程执行入参任务
        executor.execute(new Runnable() {
            @Override
            public void run() {
                // 上边判断inEventLoop方法就是判断这个thread变量,启动线程后赋值
                thread = Thread.currentThread();
                if (interrupted) {
                    thread.interrupt();
                }

                boolean success = false;
                updateLastExecutionTime();
                try {
                    // 执行NioEventLoop的run方法
                    SingleThreadEventExecutor.this.run();
                    success = true;
                } catch (Throwable t) {
                    logger.warn("Unexpected exception from an event executor: ", t);
                } finally {
                    // 忽略了很多代码
                    // 执行完毕核心内容,设置线程终止状态
                    // 移除ThreadLocal内容等等  
                }
            }
        });
    }

 

 

NioEventLoop.run方法下一章看,太复杂了

Netty服务端源码阅读笔记(三)new NioEventLoop(2)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的 Netty 服务发送消息到客户的 Java 代码示例: ```java import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; public class NettyServer { private int port; public NettyServer(int port) { this.port = port; } public void run() throws Exception { NioEventLoopGroup bossGroup = new NioEventLoopGroup(); NioEventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap bootstrap = new ServerBootstrap(); bootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new StringDecoder()); pipeline.addLast(new StringEncoder()); pipeline.addLast(new NettyServerHandler()); } }); ChannelFuture future = bootstrap.bind(port).sync(); future.channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { new NettyServer(8080).run(); } private class NettyServerHandler extends SimpleChannelInboundHandler<String> { @Override protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception { // 接收到客户的消息 System.out.println("接收到客户的消息:" + msg); // 向客户发送消息 ctx.writeAndFlush("服务已接收到消息:" + msg); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } } } ``` 在上述代码中,我们创建了一个 Netty 服务,并且在 `NettyServerHandler` 类中实现了处理客户消息的方法 `channelRead0`。在该方法中,我们打印了客户发送的消息,并且使用 `ctx.writeAndFlush` 向客户发送了一个回应消息。需要注意的是,在 Netty 中,所有的网络操作都是异步的,因此我们需要使用 `ChannelFuture` 来等待异步操作完成。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值