EventLoop和线程模型

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_25484147/article/details/85223996

JDK中的线程池

线程池的基本操作就是从线程池的空闲线程列表中选择一个Thread,并且指派它去执行一个已经提交的任务;当任务完成之后,就这个线程返回给线程池,使其可以重用。

在这里插入图片描述

缺点就是:并不能消除由上下文切换所带来的开销。

EventLoop接口

下图中所示的 是EventLoop的类层次结构
在这里插入图片描述

在这个模型中,一个EventLoop 将由一个永远都不会改变的Thread 驱动,同时任务(Runnable 或者Callable)可以直接提交给EventLoop 实现,以立即执行或者调度执行。根据配置和可用核心的不同,可能会创建多个EventLoop 实例用以优化资源的使用,并且单个EventLoop 可能会被指派用于服务多个Channel。

Netty4中的I/O和事件处理

由I/O 操作触发的事件将流经安装了一个或者多个ChannelHandler 的ChannelPipeline。传播这些事件的方法调用可以随后被Channel-Handler 所拦截,并且可以按需地处理事件。

任务调度

JDK中的任务调度API

JDK 提供了java.util.concurrent 包,它定义了interface ScheduledExecutorService。

在这里插入图片描述

这里给出两个EventLoop调度任务的两个例子

60秒之后执行


    /**
     * eventLoop60秒之后执行指定方法
     * ,这里只是输出了一行文字
     * @param channel
     */
    public static void schedule(Channel channel) {
        channel.eventLoop().schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("60 Seconds later, I run");
            }
        },60, TimeUnit.SECONDS);
    }

60秒之后执行,并且每隔60秒执行

 /**
     * 调度在60秒之后进行,而且每60秒执行一次
     * @param channel
     */
    public static void scheduleAtFixedRate(Channel channel) {
        ScheduledFuture<?> scheduledFuture = channel.eventLoop().scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println("Run Every 60 Seconds");
            }
        }, 60, 60, TimeUnit.SECONDS);
        // 这个表示是否终止
        // scheduledFuture.cancel(true);
    }

EventLoop实现细节

这里说的是Netty的线程模型和任务调度实现的内容。

线程管理

如果(当前)调用线程正是支撑EventLoop 的线程,那么所提交的代码块将会被(直接)执行。否则,EventLoop 将调度该任务以便稍后执行,并将它放入到内部队列中。当EventLoop下次处理它的事件时,它会执行队列中的那些任务/事件。每个EventLoop 都有它自已的任务队列,独立于任何其他的EventLoop。

在这里插入图片描述

EventLoop线程的分配

服务于Channel 的I/O 和事件的EventLoop 包含在EventLoopGroup 中。根据不同的传输实现,EventLoop 的创建和分配方式也不同。

异步传输

异步传输实现只使用了少量的EventLoop(以及和它们相关联的Thread),而且在当前的线程模型中,它们可能会被多个Channel 所共享。这使得可以通过尽可能少量的Thread 来支撑大量的Channel,而不是每个Channel 分配一个Thread。

显示了一个EventLoopGroup,它具有3 个固定大小的EventLoop(每个EventLoop都由一个Thread 支撑)。在创建EventLoopGroup 时就直接分配了EventLoop(以及支撑它们的Thread),以确保在需要时它们是可用的。

在这里插入图片描述

EventLoopGroup 负责为每个新创建的Channel 分配一个EventLoop。在当前实现中,使用顺序循环(round-robin)的方式进行分配以获取一个均衡的分布,并且相同的EventLoop可能会被分配给多个Channel。一旦一个Channel 被分配给一个EventLoop,它将在它的整个生命周期中都使用这个EventLoop(以及相关联的Thread)。

注意:需要注意的是,EventLoop 的分配方式对ThreadLocal 的使用的影响。因为一个EventLoop 通常会被用于支撑多个Channel,所以对于所有相关联的Channel 来说,ThreadLocal 都将是一样的。

阻塞传输

这里每一个Channel 都将被分配给一个EventLoop(以及它的Thread)。

在这里插入图片描述

,正如同之前一样,得到的保证是每个Channel 的I/O 事件都将只会被一个Thread(用于支撑该Channel 的EventLoop 的那个Thread)处理。

猜你喜欢

转载自blog.csdn.net/qq_25484147/article/details/85223996
今日推荐