如何使用netty在单独的线程池中执行业务逻辑处理程序

时间:2017-06-06 19:39:46

标签: java multithreading netty handler

我有一个需要执行某些业务逻辑的处理程序,我希望它在一个单独的线程池中执行,以便不阻塞io事件循环。我已按照http://netty.io/4.0/api/io/netty/channel/ChannelPipeline.html javadoc和http://netty.io/wiki/new-and-noteworthy-in-4.0.html#no-more-executionhandler---its-in-the-core wiki:

中的指定将DefaultEventExecutorGroup添加到管道中
ch.pipeline().addLast(new DefaultEventExecutorGroup(10), new ServerHandler());

仅出于测试目的,我的ServerHandler只是让当前线程休眠5秒钟:

protected void channelRead0(ChannelHandlerContext ctx, Command cmd) throws Exception {
    System.out.println("Starting.");

    try {
        Thread.currentThread().sleep(5000);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    System.out.println("Finished.");        
}

但显然业务逻辑仍然是同步执行的:

Starting.
Finished.
Starting.
Finished.
Starting.
Finished.

我错过了什么?

2 个答案:

答案 0 :(得分:2)

如果您的目标不是阻止IO事件循环 - 您做得对。但由于特定于netty,您的处理程序将始终附加到EventExecutorGroup的同一个线程,因此您需要执行上述行为。

如果您希望在到达时并行执行阻止操作,则需要使用另一种方式 - 单独ThreadPoolExecutor。像这样:

ch.pipeline().addLast(new ServerHandler(blockingThreadPool));

其中blockingThreadPool是常规ThreadPoolExecutor

例如:

ExecutorService blockingThreadPool = Executors.newFixedThreadPool(10);

现在,在您的逻辑处理程序中,您可以向此执行程序提交阻塞任务,如下所示:

protected void channelRead0(ChannelHandlerContext ctx, Command cmd) throws Exception {

    blockingIOProcessor.execute(new Runnable() {
        @Override
        public void run() {
            System.out.println("Starting.");

            try {
                Thread.currentThread().sleep(5000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            System.out.println("Finished.");
        }
    });

}

您还可以将上下文传递给此runnable,以便在需要时完成处理后返回响应。

答案 1 :(得分:-1)

因为Netty处理由同一个套接字通过相同EventExecutor发出的请求,所以您可以启动多个客户端,并查看结果。