zoukankan      html  css  js  c++  java
  • 耗时任务DefaultEventExecutorGroup 定时任务

    一. 耗时任务

    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处理,这就也就保证了线程安全。

     
  • 相关阅读:
    鸟哥的 Linux 私房菜Shell Scripts篇(一)
    证券投资基金会计核算业务指引
    在LINUX上部署SOFA
    bash: sz: command not found
    git常用命令
    git删除指定commit
    dubbo-本地直连
    java 中的锁 -- 偏向锁、轻量级锁、自旋锁、重量级锁
    设置Chrome忽略网站证书错误
    mybatis-传多个参数
  • 原文地址:https://www.cnblogs.com/wuer888/p/7879276.html
Copyright © 2011-2022 走看看