美文网首页nettynettyandroid技术
Netty 异步线程池处理任务

Netty 异步线程池处理任务

作者: 马路边的小破孩 | 来源:发表于2020-07-05 18:20 被阅读0次

前提

在Netty中做耗时的,不可预料的操作,比如数据库的操作,网络请求等,会严重影响Netty对Socket的处理速度。

解决方式

解决方式就是将耗时任务添加到异步线程池当中。就添加线程池这部操作来说,有2种方式:

  • handler中加入线程池
  • Context中添加线程池
    下面我们就来分析这两种方式。

1. handler中加入线程池

Server端代码:

public static void main(String[] args) {
        NioEventLoopGroup boss = new NioEventLoopGroup();
        NioEventLoopGroup worker = new NioEventLoopGroup();
        ServerBootstrap bootstrap = new ServerBootstrap().group(boss, worker)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        socketChannel.pipeline()
                                .addLast(new StringDecoder())
                                .addLast(new TaskHandler())                              
                        ;
                    }
                });
        try {
            ChannelFuture channelFuture = bootstrap.bind(8080).sync();
            channelFuture.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            boss.shutdownGracefully();
            worker.shutdownGracefully();
        }

    }

TaskHandler 代码:

public void channelActive(ChannelHandlerContext ctx) throws Exception {
        //在handler中处理耗时任务
        System.out.println("当前handler处理线程名称:"+Thread.currentThread().getName());

        ctx.channel().eventLoop().submit(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(5000L);
                    System.out.println("当前异步任务线程名称:"+Thread.currentThread().getName());
                    ctx.channel().writeAndFlush(Unpooled.copiedBuffer("hello~客户端".getBytes()));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        super.channelActive(ctx);
    }

运行打印输出结果:

当前handler处理线程名称:nioEventLoopGroup-3-2
当前异步任务线程名称:nioEventLoopGroup-3-2

2. Context中添加线程池

Netty为我们提供了一个线程池EventExecutorGroup的接口及其很多实现类,下面我们使用DefaultEventExecutorGroup 线程池异步处理任务,来对比一下 handler中异步线程执行任务的区别。

不加入DefaultEventExecutorGroup

Server端代码:

public static void main(String[] args) {
        NioEventLoopGroup boss = new NioEventLoopGroup();
        NioEventLoopGroup worker = new NioEventLoopGroup();
        ServerBootstrap bootstrap = new ServerBootstrap().group(boss, worker)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        socketChannel.pipeline()
                                .addLast(new StringDecoder())
                                .addLast(new TaskHandler())                             
                        ;
                    }
                });
        try {
            ChannelFuture channelFuture = bootstrap.bind(8080).sync();
            channelFuture.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            boss.shutdownGracefully();
            worker.shutdownGracefully();
        }
    }

TaskHandler代码:

 @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        //在handler中处理耗时任务
        System.out.println("当前handler处理线程名称:"+Thread.currentThread().getName());
        super.channelActive(ctx);
    }

运行输出执行结果(运行三个客户端):

当前handler处理线程名称:nioEventLoopGroup-4-1
当前handler处理线程名称:nioEventLoopGroup-4-2
当前handler处理线程名称:nioEventLoopGroup-4-3

加入DefaultEventExecutorGroup

Server端代码:

 public static void main(String[] args) {
        DefaultEventExecutorGroup eventExecutors = new DefaultEventExecutorGroup(4);

        NioEventLoopGroup boss = new NioEventLoopGroup();
        NioEventLoopGroup worker = new NioEventLoopGroup();
        ServerBootstrap bootstrap = new ServerBootstrap().group(boss, worker)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        socketChannel.pipeline()
                                .addLast(new StringDecoder())
                                //如果在handler前有添加EventExecutorGroup
                                //则该handler会优先添加到该线程池中
                                .addLast(eventExecutors,new TaskHandler())
                        ;
                    }
                });
        try {
            ChannelFuture channelFuture = bootstrap.bind(8080).sync();
            channelFuture.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            boss.shutdownGracefully();
            worker.shutdownGracefully();
        }
    }

Client端代码不变,和上面保持一致。
输出打印结果(运行三个客户端):

当前handler处理线程名称:defaultEventExecutorGroup-2-1
当前handler处理线程名称:defaultEventExecutorGroup-2-2
当前handler处理线程名称:defaultEventExecutorGroup-2-3

对比我们可以看出来,如果在handler前有添加DefaultEventExecutorGroup , 则该handler会优先添加到该线程池中,处理任务的线程池不在是NioEventLoopGroup。

3.两种方式比较

1.第一种方式在handler中添加异步,可能更加的自由,比如如果需要访问数据库,那我就异步,如果不需要就不异步,异步会拖长接口响应时间。因为需要将任务放进task中,如果IO时间很短,task很多,可能一个循环下来,都没时间执行整个task,导致响应时间不达标。

  1. 第二中方式是Netty标准方式即加入到队列,但是这么做会将整个handler都交给业务线程池,不论耗时不耗时都加入队列,不够灵活。
    3.各有优劣,灵活性来说,第一种好。

相关文章

  • Netty 异步线程池处理任务

    前提 在Netty中做耗时的,不可预料的操作,比如数据库的操作,网络请求等,会严重影响Netty对Socket的处...

  • Netty——任务加入异步线程池

    前言 我们常常遇到这样的需求:在一个业务逻辑处理器中,需要写数据库、进行网络连接等耗时业务。Netty的原则是不阻...

  • Android性能优化之使用线程池处理异步任务

    zhengxiaoyong.me/2015/11/17/Android性能优化之使用线程池处理异步任务/

  • Netty高级功能(三):性能指标采集监控

    1、Netty I/O线程池性能统计 线程池(workGroup)中待线程(NioEventLoop)处理的消息队...

  • 聊聊Java线程池原理

    线程池是很常用的并发框架,几乎所有需要异步和并发处理任务的程序都可用到线程池。使用线程池的好处如下: 降低资源消耗...

  • 2020-06-17

    阐述背景 线程池在日常工作中用的还挺多,当需要异步,批量处理一些任务的时候我们会定义一个线程池来处理。 在使用线程...

  • 3. Dubbo线程池模型

    dubbo有两种线程池,io线程池、业务线程池以netty作为io框架为例:boss线程池: 主要处理新的连接请求...

  • java并发基础-线程池

    线程池主要解决两个问题:当执行大量异步任务时线程池能够提供较好的性能。在不使用线程池时,每当需要执行异步任务时直接...

  • 线程池

    多线程使用:使用注解方式注入线程池进行异步任务,避免手动方式创建线程池

  • 一篇文章搞懂线程池

    线程池 什么使用使用线程池? 单个任务处理时间比较短 需要处理的任务数量很大 线程池优势 重用存在的线程,减少线程...

网友评论

    本文标题:Netty 异步线程池处理任务

    本文链接:https://www.haomeiwen.com/subject/rilbfktx.html