netty 之 耗时任务DefaultEventExecutorGroup 定时任务

本文详细解析了Netty中EventExecutorGroup的作用,如何在耗时任务和计划任务中正确使用,以及如何避免阻塞IO线程。重点讨论了在指定EventExecutorGroup和默认情况下处理任务的差异,并提供了实例代码说明。
摘要由CSDN通过智能技术生成

一. 耗时任务

static final EventExecutorGroup group = new DefaultEventExecutorGroup(16);

 // Tell the pipeline to run MyBusinessLogicHandler's event handler methods
 // in a different thread than an I/O thread so that the I/O thread is not blocked by
 // a time-consuming task.
 // If your business logic is fully asynchronous or finished very quickly, you don't
 // need to specify a group.
 pipeline.addLast(group, "handler", new MyBusinessLogicHandler());

其中EventExecutorGroup 就是专门来处理耗时业务的线程池。

childHandler(new ChannelInitializer<SocketChannel>() {

static final EventExecutorGroup group = new DefaultEventExecutorGroup(16);

@Override
protected void initChannel(SocketChannel ch)
throws Exception {
ChannelPipeline p = ch.pipeline();pipeline.addLast(group, "handler", new MyBusinessLogicHandler());

 

此方法所在类 每次都是new  ,所以会创建很多group,  所以把group 定义为static

二.执行计划

 

在实际生产环境中,我们可能会碰到 需要临时执行也行计划任务,,这些任务如果不耗时,我们可以通过channel提供的计划任务方法处理:

future =  channel.eventLoop.scheduleAtFixedRate(new Runnable() {

            @Override
            public void run() {
                            //逻辑代码,非耗时任务
               }
        }, 6, 6, TimeUnit.HOURS);
       ....

如果计划任务里面的逻辑比较耗时,那么就不能再用eventLoop,因为这会阻塞IO线程。如果是通过pipeline.addLast(group, "handler", new MyBusinessLogicHandler()); 这种方式添加的业务线程我们可以使用下面的方式添加计划任务方法实现:

***future = ctx.executor().scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
            }
        }, 6, 6, TimeUnit.HOURS);***

...

netty 源码

public EventExecutor executor() {
        return (EventExecutor)(this.executor == null?this.channel().eventLoop():this.executor);
    }

如果this.executor为null,就返回channel().eventLoop(),这个是io读写线程,肯定是不能执行耗时任务的。
如果不为空,那么是怎么传进来的呢?

DefaultChannelPipeline

public final ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler) {
        final AbstractChannelHandlerContext newCtx;
        synchronized(this) {
            checkMultiplicity(handler);
            newCtx = this.newContext(group, this.filterName(name, handler), handler);
private AbstractChannelHandlerContext newContext(EventExecutorGroup group, String name, ChannelHandler handler) {
        return new DefaultChannelHandlerContext(this, this.childExecutor(group), name, handler);
    }

通过源码发现:其实就是我们在添加handler时指定的DefaultEventExecutorGroup。
所以结论是:如果在处理耗时任务的Handler添加时用到了DefaultEventExecutorGroup是可以 ctx.executor().scheduleAtFixedRate这么用的,但是如果你再添加handler时没有没有指定特殊的EventExecutorGroup,是不能执行耗时任务的。

如果是在IO线程,如果想处理耗时任务逻辑,那么就需要新建一个EventExecutorGroup,并调用他的相关方法


EventLoop:其本质是一个用来处理IO事件的线程,EventLoopGroup 其本质是一个线程池。一个EventLoop可以和多个Channel绑定,处理多个Channel的IO事件;但是一个Channel在整个生命周期内只会被一个EventLoop处理,这就也就保证了线程安全。

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Netty是一个基于Java的高性能网络通信框架,它提供了一些方便的功能,包括时间轮定时任务。时间轮是一种用于执行定时任务的数据结构,它可以提高定时任务的触发精度和执行效率。 在Netty中,时间轮定时任务是通过`HashedWheelTimer`类实现的。下面是一个简单的示例代码,演示如何在Netty中使用时间轮定时任务: ```java import io.netty.util.HashedWheelTimer; import io.netty.util.Timeout; import io.netty.util.TimerTask; public class TimeWheelExample { public static void main(String[] args) { // 创建时间轮定时器 HashedWheelTimer timer = new HashedWheelTimer(); // 创建定时任务 TimerTask task = new TimerTask() { @Override public void run(Timeout timeout) throws Exception { System.out.println("定时任务执行"); } }; // 将定时任务提交给时间轮定时器,延迟2秒后执行 timer.newTimeout(task, 2, TimeUnit.SECONDS); } } ``` 在上面的示例中,我们首先创建了一个`HashedWheelTimer`实例,然后创建了一个`TimerTask`对象,定义了要执行的定时任务。最后,我们使用`timer.newTimeout()`方法将定时任务提交给时间轮定时器,并指定了延迟时间为2秒。 当时间轮定时器触发定时任务时,会调用`run()`方法执行任务。在这个例子中,定时任务执行时,会简单地打印一条消息。 需要注意的是,时间轮定时任务仅限于在Netty中使用,如果你想在其他环境或框架中使用时间轮定时任务,可能需要使用其他的定时任务实现方式。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值